Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Calling PowerShell script from HTA

Status
Not open for further replies.

withanh

IS-IT--Management
Dec 17, 2008
221
US
I have an HTA that I'm writing that writes and calls a PowerShell script. The PS script interrogates Exchange to find who has ActiveSync enabled. This is used later in the main script for looking at ActiveSync devices and controlling them. The PS script works perfectly when run as a stand-alone PS script.

When I open the HTA in my editor (I use HtaEdit from and run the HTA, the PS script runs perfectly.

When I run the HTA directly the PS script fails. The error message is:
[red]
Code:
File C:\ActiveSyncUsers\ActiveSyncUsers.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.
At line:1 cahr:42
+ & {C:\ActiveSyncUsers\ActiveSyncUsers.ps1 <<<< }
    + CategoryInfo          : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException
[/red]

Any ideas why this PS script fails when it runs from within the HTA?

The command I am using in the HTA to run the PS script is:
Code:
strPowershellScript = "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin" & vbCrLf & _
"Get-ActiveSyncDeviceStatistics -Mailbox " & Identity & " | Select DeviceID, DeviceType | fl | out-file C:\ActiveSyncUsers\ActiveSyncUsers.txt"
RunPowershell strPowershellScript

Sub RunPowershell(Script)
  Set objFile = objFSO.OpenTextFile("C:\ActiveSyncUsers\ActiveSyncUsers.ps1",ForWriting,Overwrite,Unicode)
  objFile.Write Script
  objFile.Close
  objShell.Run "Powershell -command ""& {C:\ActiveSyncUsers\ActiveSyncUsers.ps1}""",ShowWindow,WaitToFinish
End Sub
 
No, but it sounds like another good reason to move off Microsoft's phone platform.
 
try something like this
Code:
powershell -ExecutionPolicy RemoteSigned .\ActiveSyncUsers.ps1
 
@dilettante I fail to see how this has anything to do with Microsoft's phone platform. We do not have any Microsoft phones in our environment. It's ActiveSync which is how iPhones & Android phones connect to Exchange. Not to mention that this is a PowerShell script execution issue and really has nothing to do with ActiveSync.



@mikrom,

Are you suggesting use that as part of the line that executes the script, or just do that to sign the PS script? Or throw that in every time right before I run the script to sign that instance of it?

Something like:
Code:
Sub RunPowershell(Script)
  Set objFile = objFSO.OpenTextFile("C:\ActiveSyncUsers\ActiveSyncUsers.ps1",ForWriting,Overwrite,Unicode)
  objFile.Write Script
  objFile.Close
  objShell.Run "powershell -ExecutionPolicy RemoteSigned C:\ActiveSyncUsers\ActiveSyncUsers.ps1"
  objShell.Run "Powershell -command ""& {C:\ActiveSyncUsers\ActiveSyncUsers.ps1}""",ShowWindow,WaitToFinish
End Sub

I ask because it's kind of a dynamic script, it gets built and destroyed a few times during the whole HTA. And none of the other PS scripts have an issue running, only this one that kicks off when the script launches.

Thanks,

Darhl
 
withanh said:
Are you suggesting use that as part of the line that executes the script .. ?
Yes. I have often the same problem and using the above command line option to fix it.
 
I tried the following example with a powershell script I posted here:

run_ps1_script.vbs
Code:
cmd_str [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]"powershell .\split_example.ps1"[/color]
run_command[COLOR=#804040][b]([/b][/color]cmd_str[COLOR=#804040][b])[/b][/color]
cmd_str [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]"powershell -ExecutionPolicy RemoteSigned .\split_example.ps1"[/color]
run_command[COLOR=#804040][b]([/b][/color]cmd_str[COLOR=#804040][b])[/b][/color]

[COLOR=#804040][b]sub[/b][/color] run_command[COLOR=#804040][b]([/b][/color]command_string[COLOR=#804040][b])[/b][/color]
  [COLOR=#804040][b]set[/b][/color] objShell [COLOR=#804040][b]=[/b][/color] WScript[COLOR=#804040][b].[/b][/color][COLOR=#008080]CreateObject[/color][COLOR=#804040][b]([/b][/color][COLOR=#ff00ff]"WScript.Shell"[/color][COLOR=#804040][b])[/b][/color]
  run_result[COLOR=#804040][b]=[/b][/color]objShell[COLOR=#804040][b].[/b][/color]run[COLOR=#804040][b]([/b][/color]command_string[COLOR=#804040][b],[/b][/color] [COLOR=#ff00ff]4[/color][COLOR=#804040][b],[/b][/color] [COLOR=#ff00ff]true[/color][COLOR=#804040][b])[/b][/color]
  wscript[COLOR=#804040][b].[/b][/color]echo[COLOR=#804040][b]([/b][/color][COLOR=#ff00ff]"run_result = "[/color] [COLOR=#804040][b]&[/b][/color] run_result[COLOR=#804040][b])[/b][/color]
  [COLOR=#804040][b]if[/b][/color] run_result [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]0[/color] [COLOR=#804040][b]then[/b][/color]
    wscript[COLOR=#804040][b].[/b][/color]echo[COLOR=#804040][b]([/b][/color][COLOR=#ff00ff]"command completed succesfully"[/color][COLOR=#804040][b])[/b][/color]
  [COLOR=#804040][b]else[/b][/color]
    wscript[COLOR=#804040][b].[/b][/color]echo[COLOR=#804040][b]([/b][/color][COLOR=#ff00ff]"command failed !"[/color][COLOR=#804040][b])[/b][/color]
  [COLOR=#804040][b]end[/b][/color] [COLOR=#804040][b]if[/b][/color]
  [COLOR=#804040][b]set[/b][/color] objShell [COLOR=#804040][b]=[/b][/color] [COLOR=#804040][b]Nothing[/b][/color]
[COLOR=#804040][b]end[/b][/color] [COLOR=#804040][b]sub[/b][/color]
Output:
Code:
c:\_mikrom\Work\PowerShell>cscript /NoLogo run_ps1_script.vbs
run_result = 1
command failed !
run_result = 0
command completed succesfully
You see, that in the first case the powershell script failed to execute.
But in the second case when I used the option -ExecutionPolicy RemoteSigned the script completed succesfully.
 
I wonder what user context the script runs in. Now when I run this, it tells me that the PowerShell snap-in 'Microsoft.Exchange.Management.PowerShell.Admin' is not installed on this machine. But it is, when I run the PS script separately it runs just fine. Just can't quite figure it out.

The error message in its entirety is:
[red]
Code:
Add-PSSnapin : The Windows PowerShell snap-in 'Microsoft.Exchange.Management.PowerShell.Admin' is not installed on this machine.
At C:\Scripts\ActiveSync\ActiveSyncUsers.ps1:1 char:13
+ Add-PSSnapin <<<<  Microsoft.Exchange.Management.PowerShell.Admin
    + CategoryInfo          : InvalidArgument: (Microsoft.Excha...owerShell.Admin:String) [Add-PSSnapin], PSArgumentException
    + FullyQualifiedErrorId : AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommand

The term 'Get-CASMailbox' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Scripts\ActiveSync\ActiveSyncUsers.ps1:2 char:15
+ Get-CASMailbox <<<<  -resultsize unlimited | where {$_.ActiveSyncEnabled} | Select DisplayName,SamAccountName | fl | out-file ./ActiveSyncUsers.txt
    + CategoryInfo          : ObjectNotFound: (Get-AASMailbox:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
[/red]
So it seems like the script is running now, but for some reason in this context it cannot see the Exchange Management snap-in to initialize.

Also, none of the other PS scripts are working with the same error now. They were working previously (they take the output from the first script (users) and find what ActiveSync devices that user has).
 
withanh said:
I wonder what user context the script runs in. Now when I run this, it tells me that the PowerShell snap-in 'Microsoft.Exchange.Management.PowerShell.Admin' is not installed on this machine. But it is, when I run the PS script separately it runs just fine.
I have a question: When the powershel script runs fine separately, why want you call the script from Vbscript.
Would it not be simpler and better to use only powershell without Vbscript ?
I cannot simulate your case exactly, but despite my question, IMHO it should be possible to run powershell scripts from Vbscript.
 
I'm trying to build a poor man's ActiveSync manager. Basically, the goal is to check the Exchange infrastructure and see who has ActiveSync enabled. Us that to populate a drop-down list. Pick a name from the list and it kicks off another PS script (that works just fine) that asks Exchange what devices the user has and display those devices with check boxes. Then I can select the check boxes for the authorized devices and submit it and another PS script will kick off telling Exchange to only allow those devices. This will help us to keep unauthorized devices from connecting.

I don't know enough about PowerShell to write the GUI pieces, but doing it in an HTA was a relatively easy transition from VBS.

The script is intended to run on the Exchange Server or a management workstation that has the Exchange Tools installed. I use Exch07 so I don't know if it will work with Exch10.

The script in its entirety is:
Code:
<html>
<head>
  <title>Allow ActiveSync Devices</title>
  <HTA:APPLICATION
  APPLICATIONNAME = "ActiveSync Users"
  ID              = "="
  VERSION         = "1.4"
  SINGLEINSTANCE  = "yes"/>
  <style type     = "text/css">
    div.footer{
      position:absolute;
      bottom:9px;
      }
    div.debug{
      position:absolute;
      width:250px;
      bottom:5px;
      left:50px;
      }
  </style>
</head>

<script language = "VBScript">
  Option Explicit
' On Error Resume Next

  Dim strResult, strCombo, strExit, strDebug, strScript, strReadLine, strTemp, strTemp2
  Dim strDeviceType, strDeviceID, strUserID, strUserName, strAllowed, setTimer, x, y
  Dim objFSO, objFile, objShell, objCheckBox
  Dim arrUserID(), arrUserName(), arrDeviceID(), arrDeviceType(), chkDevices()

  Const ForReading    = 1
  Const ForWriting    = 2
  Const ForAppending  = 8
  Const ASCII         = 0
  Const Unicode       = -1
  Const Overwrite     = True
  Const ReadOnly      = False
  Const HideWindow    = 0
  Const ShowWindow    = 1
  Const WaitToFinish  = True
  Const DebugIt       = True
	
  strExit = "<input id = runbutton type = ""button"" value = ""Exit"" onClick = ""btnExit_OnClick"">"

  Set objShell = CreateObject("WScript.Shell")
  Set objFSO = CreateObject("Scripting.FileSystemObject")  
  Sub Window_OnLoad
    Window.ResizeTo 640,480
    Window.MoveTo 150,150
    strCombo = "<i>Loading users, please wait...</i>"
    divCombo.InnerHTML = strCombo
    divResult.InnerHTML = "<center><br><br><img src = ""activesync2.png"" height = ""150"" width = ""150""></center>"
    Set objFile = objFSO.OpenTextFile("./RunPowerShell.bat",ForWriting,Overwrite)
    strScript = "powershell -ExecutionPolicy RemoteSigned ./ActiveSyncUsers.ps1" & vbCrLf & _
                "rem powershell -ExecutionPolicy RemoteSigned ./ActiveSyncUsers.ps1"
    objFile.Write strScript
    objFile.Close
    strScript = ""
    GetActiveSyncUsers
    Populate_strCombo
    divExit.InnerHTML = strExit
  End Sub

  Sub Populate_strCombo
    strCombo = "<select id=""cboUsers"" name=""cboUsers"" onchange=""cboUsers_OnChange"">" & vbcrlf
    For x = 0 To UBound(arrUserName)
      strCombo = strCombo & "<option value = """ & x & """>" & arrUserName(x) & "</option>" & vbCrLf
    Next
    strCombo = strCombo & "</select>"
    divCombo.InnerHTML = strCombo
    strResult = ""
    divResult.InnerHTML = strResult
    strDebug = ""
    divDebug.InnerHTML = strDebug
    DebugCode strResult
    End Sub

  Sub cboUsers_OnChange
    setTimer = Window.setTimeout("UpdateDevices", 100, "VBScript")
  End Sub

  Sub UpdateDevices
    Window.ClearTimeout(setTimer)
    divExit.InnerHTML = ""
    strResult = "<i>Retrieving ActiveSync devices for " & arrUserName(cboUsers.Value) & "<br>Please wait...</i><br><center><img src = ""activesync2.png"" width = ""150"" height = ""150""></center>"
    divResult.InnerHTML = strResult
    GetActiveSyncDevices arrUserID(cboUsers.Value)
    strResult = strResult & "<i><font color=""red"" size=""1"">*If no devices are selected then all devices will be allowed</font></i><br><br>" & vbCrLf
    strResult = strResult & "<input type=""button"" value=""Submit"" name=""btnSubmit"" onClick=""btnSubmit_OnClick"">" & vbCrLf
    strResult = strResult & "&nbsp; <input type=""button"" value=""Cancel"" name=""btnCancel"" onclick=""btnCancel_OnClick"">"
    divResult.InnerHTML = strResult
    DebugCode strResult
    strCombo = "Please select the devices you would like to allow<br>for " & arrUserName(cboUsers.Value) & "<br><br>"
    divCombo.InnerHTML = strCombo
    divExit.InnerHTML = strExit
  End Sub 

  Sub btnSubmit_OnClick
    strAllowed = ""
    For x = 0 To UBound(arrDeviceID)
      Set objCheckBox = Document.GetElementById("chkDevices" & x)
      If objCheckBox.Checked Then
        If strAllowed = "" Then
          strAllowed = objCheckBox.Value
        Else
          strAllowed = strAllowed & "," & objCheckBox.Value
        End If
      End If
    Next
    If strAllowed = "" Then
      strAllowed = "all devices"
      strScript = "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin" & vbCrLf & _
                  "Set-CasMailbox " & arrUserID(cboUsers.Value) & " -ActiveSyncAllowedDeviceIDs:$null"
      'RunPowershell strScript
    Else
      strScript = "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin" & vbCrLf & _
                  "Set-CasMailbox " & arrUserID(cboUsers.Value) & " -ActiveSyncAllowedDeviceIDs " & strAllowed
      'RunPowershell strScript
    End If
  End Sub

  Sub GetActiveSyncUsers
    Document.body.style.cursor = "wait"
    strScript = "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin" & vbCrLf & _
                "Get-CASMailbox -resultsize unlimited | where {$_.ActiveSyncEnabled} | Select DisplayName,SamAccountName | fl | out-file ./ActiveSyncUsers.txt"
    RunPowershell strScript
    Set objFile = objFSO.OpenTextFile("./ActiveSyncUsers.txt",ForReading,ReadOnly,Unicode)
    x = 1
    ReDim arrUserID(x), arrUserName(x)
    Do Until objFile.AtEndOfStream
      strReadLine = objFile.ReadLine
      If strReadLine <> "" Then
        If Left(strReadLine,11) = "DisplayName" Then
          ReDim Preserve arrUserName(x)
          strReadLine = Replace(strReadLine,"DisplayName","")
          strReadLine = Replace(strReadline,":","")
          arrUserName(x) = Trim(strReadLine)
        ElseIf Left(strReadLine,14) = "SamAccountName" Then
          ReDim Preserve arrUserID(x)
          strReadLine = Replace(strReadLine,"SamAccountName","")
          strReadLine = Replace(strReadline,":","")
          arrUserID(x) = Trim(strReadLine)
          x = x + 1
        End If
      End If
    Loop
    objFile.Close
    'Alphabetize array
    For x = UBound(arrUserName) -1 To 0 Step -1
      For y = 0 to x
        If arrUserName(y) > arrUserName(y + 1) Then
          strTemp = arrUserName(y + 1)
          strTemp2 = arrUserID(y + 1)
          arrUserName(y + 1) = arrUserName(y)
          arrUserID(y + 1) = arrUserID(y)
          arrUserName(y) = strTemp
          arrUserID(y) = strTemp2
        End If
      Next
    Next
    arrUserName(0) = "Select a user"
    arrUserID(0) = "Select a user"
    Document.body.style.cursor = "default"
  End Sub

  Sub GetActiveSyncDevices(Identity)
    Document.body.style.cursor = "wait"
    strScript = "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin" & vbCrLf & _
                "Get-ActiveSyncDeviceStatistics -Mailbox " & Identity & " | Select DeviceID, DeviceType | fl | out-file ./ActiveSyncUsers.txt"
    RunPowershell strScript
    Set objFile = objFSO.OpenTextFile("./ActiveSyncUsers.txt",ForReading,ReadOnly,Unicode)
    strResult = ""
    x = 0
    ReDim arrDeviceID(x)
    ReDim arrDeviceType(x)
    Do Until objFile.AtEndOfStream
      strReadLine = objFile.ReadLine
      If Left(strReadLine,8) = "DeviceID" Then
        ReDim Preserve arrDeviceID(x)
        strReadLine = Replace(strReadLine,"DeviceID","")
        strReadLine = Replace(strReadline,":","")
        arrDeviceID(x) = Trim(strReadLine)
        strResult = strResult & "<input type=""checkbox"" name=""chkDevices" & x & """ value=""" & arrDeviceID(x) & """>"
      ElseIf Left(strReadLine,10) = "DeviceType" Then
        ReDim Preserve arrDeviceType(x)
        strReadLine = Replace(strReadLine,"DeviceType","")
        strReadLine = Replace(strReadline,":","")
        arrDeviceType(x) = Trim(strReadLine)
        strResult = strResult & arrDeviceType(x) & " - " & arrDeviceID(x) & "<br>" & vbCrLf
        x = x + 1
      End If
    Loop
    objFile.Close
    If strResult = "" Then strResult = "No Devices"
    divResult.InnerHTML = strResult
    DebugCode strResult
    Document.body.style.cursor = "default"
  End Sub

  Sub RunPowershell(Script)
    Set objFile = objFSO.OpenTextFile("./ActiveSyncUsers.ps1",ForWriting,Overwrite,Unicode)
    objFile.Write Script
    objFile.Close

'    objShell.Run "RunPowerShell.bat",ShowWindow,WaitToFinish
    objShell.Run "Powershell -ExecutionPolicy RemoteSigned ./ActiveSyncUsers.ps1",ShowWindow,WaitToFinish
'    objShell.Run "Powershell -command ""& {./ActiveSyncUsers.ps1}""",ShowWindow,WaitToFinish
  End Sub

  Sub btnCancel_OnClick
    Populate_strCombo
  End Sub

  Sub btnExit_OnClick
    divCombo.InnerHTML  = "<i>Cleaning up, please wait...</i>"
    divResult.InnerHTML = ""
    divExit.InnerHTML   = ""
    divDebug.InnerHTML  = ""
    objFSO.DeleteFile("./ActiveSyncUsers.ps1")
    objFSO.DeleteFile("./ActiveSyncUsers.txt")
    objFSO.DeleteFile("./RunPowerShell.bat")
    Set objCheckBox     = Nothing
    Set objShell        = Nothing
    Set objFile         = Nothing
    Set objFSO          = Nothing
    window.close()
  End Sub

 Sub DebugCode(HTML)
    If DebugIt = True Then
      divDebug.InnerHtml = "<xmp>" & HTML & "</xmp>"
    End If
  End Sub

</script>

<body bgcolor = "white">
  <div id = "divCombo" name = "divCombo">&nbsp;</div>
  <div id = "divResult" name = "divResult">&nbsp;</div>
  <div id = "divDebug" name = "divDebug" class = "debug">&nbsp;</div>
  <div id = "divExit" name = "divExit" class = "footer">&nbsp;</div>
</body>

</html>
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top