VBScript - StartMode Returning Unknown for Service in WinXP (but not Win7) - service

Ahh...so frustrated...hopefully someone here can help!
There is a software product called ScreenConnect that allows you to install it on your own server and through this install set up attended and unattended remote access sessions. I use this with a lot of my clients, but it's a lot easier to set up unattended installs on those client's machines that I'm going to be needing access to more than once. However, a few clients want to have control over when I can remote in and when I can't, and since the software product doesn't yet have this functionality built into it, I figured I'd just create two vbscript files on their desktops - one that turns off the service if it's on (and vice versa), and the other that changes the startup type of the service to automatic (if it's set to manual) and vice versa. I was able to pretty easily get the start/stop service vbscript file going:
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colRunningServices = objWMIService.ExecQuery _
("select State from Win32_Service where Name LIKE '%ScreenConnect%'")
For Each objService in colRunningServices
Wscript.Echo "State: " & objService.State
If objService.State <> "Running" Then
errReturn = objService.StartService()
Wscript.Echo "FalconRemote Started"
Else
errReturn = objService.StopService()
Wscript.Echo "FalconRemote Stopped"
End If
Next
However, for the life of me, I can't get the automatic/manual start-up type vbscript working on Windows XP. If I simplify it down to the bones and just want to have the vbscript tell me the current status of the startup (i.e. manual, automatic, disabled), which is obviously necessary for the vbscript to know so it can determine what to do based on that information, then this is what I put together:
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colRunningServices = objWMIService.ExecQuery _
("select StartMode from Win32_Service where Name LIKE '%ScreenConnect%'")
For Each objService in colRunningServices
Wscript.Echo "StartMode: " & objService.PathName
Next
And yet, that returns "Unknown" instead of an acceptable value like "Manual", "Disabled", or "Autoamtic" - I have no idea why it's returning "Unknown"!!!
I've tried changing the fifth line to this:
("select * from Win32_Service where Name LIKE '%ScreenConnect%'")
or this
("select StartMode from Win32_Service where DisplayName LIKE '%ScreenConnect%'")
but it seems to have no effect.
If I change out ScreenConnect in the above script for another service, like helpsvc (using Name) or Help and Support (using DisplayName), it works! And it works fine on a Windows 7 machine. Why does it not work on a Windows XP machine? Any ideas???? I tried installing Mozilla Firefox 20 (with the Mozilla Maintenance Service) and it works fine reading the startmode of that service (which isn't built into WinXP), so why won't it read the startmode of this service?
Any help is greatly appreciated!
Thanks.
Marc

I've just recently encountered this issue.
I'm not exactly sure how the windows service was put in this state, but it seems that the windows service is in an "Unknown" state.
For example, it could be that the executable no longer exists on the file system, but the windows service (registry) entry still (partially) exists.
In any case, simply deleting the windows service entry resolved the issue.
The windows service can be deleted using the following command line for example:
sc delete "ScreenConnect service name"

Related

HP BIOS Battery Health Settings

I am attempting to change the BIOS battery charging settings with PowerShell and will eventually deploy it using Intune. I am interested in doing this because I have some users that leave their computers plugged in full-time and it ruins the battery within a year. Changing this setting will only allow the computer to charge up to a specified limit which will hopefully increase the batteries overall lifespan.
I am having issues with my code which is giving me a "The Term ' ' is not recognized as the name of a cmdlet, functions, script file, or operable program". I am using the following documentation to create the script and am using an HP computer that has been verified to have this setting in the BIOS.
https://developers.hp.com/hp-client-management/blog/managing-battery-health-settings-hpcmsl-and-intune
$setting = Get-HPBIOSSettingValue -Name "Battery Health Manager"
if ($setting -eq "Let HP manage my battery charging") {
exit 0
}
Set-HPBIOSSettingValue -Name "Battery Health Manager" -value "Let HP manage my battery charging"
exit 0
For the purpose of this exercise I don't really need to test the detect script because I already know what this setting is set to. Does anyone know what I am doing wrong? The script also failed when I saved it as a .ps1. I have a feeling there is something very basic that I am missing because I am new to powershell.
Sounds like you don't have the HP Powershell module installed.
The command Get-HPBIOSSettingValue and Set-HPBIOSSettingValue are not native to Windows - you'll need to download the relevant HP module and install it - try Powershell Gallery.

PowerShell - showing a message on remote computer screen

When I am running commands or installing software remotely using PowerShell - Invoke-Command etc I would like sometimes to be able to show a message on the remote screen so the user knows something is happening, or when work done etc.
I would like to if possible make this message look as professional as possible, e.g. better than just a standard winform message box if it can be done? perhaps more the style of the Windows 10 ones with coloured background and use of image if possible.
Spent a while googling but most seem to relate to using obsolete methods such as net-send or using msg.exe.
Thanks
https://michlstechblog.info/blog/powershell-show-a-messagebox/
So the issue really isnt creating the messagebox itself, its having it show on the users session.
So when you run a command against a system, youre using your creds to run the command therefore it wont show in the users session. You can get around this by running it in the users context using a task scheduler. I have a script that does all this for you but, id hate to recreate the wheel and will have to wait till monday (when im at work) to post it here.
It accepts user input in your sessions that outputs it to a vbs, which then copies it over the message to the users machine, and a task schedule is set to run immediately for the user thats logged in.
edit: The script is this without the task scheduler. I just invoke gwmi win32_computersystem | Select -ExpandProperty username to get the current user logged in and add it to the task.
#Prompt for messge
$strMSG = Read-Host -Prompt "Enter message"
#deleting vbs if it exists
del C:\brief\test.vbs
#creating vbs from scratch so it doesnt override
New-Item C:\brief\test.vbs
#Appending each the values to a seperate line
Add-Content C:\brief\test.vbs 'Set objShell = Wscript.CreateObject("WScript.Shell")'
Add-Content C:\brief\test.vbs "strText = `"$strMSG`""
Add-Content C:\brief\test.vbs 'intButton = objShell.Popup(strText,0,"Computer Support",48)'
#calling on the script
& cscript C:\brief\test.vbs
Found a great solution here which appears on quick testing to work well for displaying a toast notification on a remote machine
https://smsagent.blog/2019/06/11/just-for-fun-send-a-remote-toast-notification/

Automatically name Computer using PowerShell get host name and MDT

My question is if it is possible to obtain the Domain Name of a computer in a Enterprise environment and use it as computer name in a MDT deployment.
I am aware that MDT has an option for setting the computer name here: Right cklick on Deployment Share - Rules
I would love to use the variable $CNAME (Computer Name) which I can successfully obtain using the follwing powershell commands as a variable for “OSDComputerName=“ in the deploymentshare settings.
This ps script gets me the right name:
1 Get IP
$IP=((ipconfig | findstr [0-9].\.)[0]).Split()[-1]
2 Do NSLOOKUP of IP
$Lookup=NSLOOKUP $IP
3 Adjust output with regular expressions and -replace modifiers to only contain the real computername without DNS suffix
$regex=$Lookup -match "(^.*\bName\b\:?\s*\b)[\w\d\s\-]*"
$replace1=$regex -replace "Name: "
$CNAME=$replace1 -replace "*DNSSUFFIX*"
Is this possible? Otherwise, can I use the PowerShell Script in any way to rename the computer after the deployment has finished? E.g. which command can I use to use the variable $CNAME as new computer name?
The following Script will use the IP Adress to query your DNS and get the name of the Computer in your Domain and pass it back to MDT as OSDComputerName
This works in an environment where the computers are named like name.xx.yournamespace.de
Add an nslookup.exe from a Windows ISO to your WinPE Boot Image (mount WinPE WIM with DISM and copy nslookup.exe into System32)
Adjust your customsettings.ini Rules, add:
UserExit=Setname.vbs
OSDComputerName=#SetName("%IPAddress%")#
Add a UserExit Script to your Deploymentshare Scripts-Folder, name it Setname.vbs
Function UserExit(sType, sWhen, sDetail, bSkip)
UserExit = Success
End Function
Function SetName(sIP)
Dim rName
Set objShell = createobject("wscript.shell")
strParams = "%comspec% /c nslookup " & sIP & ""
Set objExecObj = objShell.exec(strParams)
Do While Not objExecObj.StdOut.AtEndOfStream
strText = objExecObj.StdOut.Readline()
If instr(strText, "dns-9") Then
strServer = trim(replace(strText,"(null):",""))
Elseif instr (strText, "xx.yournamespace.de") Then
strhost = trim(replace(strText,"(null)",""))
End if
Loop
rName = replace(strhost, ".xx.yournamespace.de", "")
SetName = rName
End Function
Adjust replacements to your Network. SetName will be passed back to MDT.
Hopefully this helps someone!

How can we recognize two excel.exe proceeses opened by different object?

I have an .vbs file which is working on an Excel workbook. now suppose a situation arsie where in the system 3 EXCEL.EXE processes are running.So now is there any way to find out which one is opened by a main.vbs script?
Even though you tagged this powershell, here's a VBS only option will may need some tinkering depending on your Excel version (I have 2003 on this pc):
'Create Excel Application for demo purposes only
Dim ex: Set ex = CreateObject("Excel.Application")
Dim objWMIService, objProcess, colProcess
Dim strComputer, strList
strComputer = "." 'Change if you want to run on another computer
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
'Look only at Excel process name
Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process Where NAME = 'EXCEL.exe'")
'Get the list of Processes, included only for demo purposes
For Each objProcess In colProcess
strList = strList & vbCr & objProcess.commandline
Next
MsgBox strList ' Displayed "C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE"
'"C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE" / automation - Embedding
' Second row was the created Object.
'Find processes that match the Created Object format commandline
Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process Where CommandLine Like '%EXCEL.exe"" /automation -Embedding'")
For Each objProcess In colProcess
'Do something with process
objProcess.Terminate
Next
'Next line will cause runtime error due to process already being terminated.
ex.Quit
The beauty of methods similar to this is that by using the objProcess.Commandline you can find command-line switches sent to the application which you can use to pinpoint a specific process. For instance, if you had a .bat file that opened an Excel file like this : start Excel.exe C:\example.xls the process would include C:\example.xls within the process Commandline property.
Use Get-WMIObject win32_process to get a list of all the processes. Look at ParentProcessId member to see which process has spawned which Excel instance.
VBScripts are executed via WScript or CScript, so you need to look at the correct parent first.
Be aware that Windows does recycle process ids. That is, at time t0 pid 1000 is not necessarily the same process as at time t1.
Addendum:
Use -Computername switch to specify another a computer for the WMI query. If no -Computername switch is present, localhost is assumed. Local host is also known as ., which was used in the VBScript answer above. Like so,
#Get process list from Server01, assuming you have sufficient rights
Get-WMIObject win32_process -Computername server01

Start/Stop App Pool IIS6.0 with Powershell or command line

I'm using IIS 6.0 and looking for a way to stop/start the app pool. I know there is a stop-appPool for powershell in 7.0 but using 6.0. :-( So does anyone have a powershell script or another command line exe that will stop/start the app pool?
Thanks.
Ok here it is, I just add a switch to stop the app pool else it starts since no harm in starting an app pool that is already started:
param([string]$appPoolName, [switch]$stop)
$appPool = get-wmiobject -namespace "root\MicrosoftIISv2" -class "IIsApplicationPool" | where-object {$_.Name -eq "W3SVC/AppPools/$appPoolName"}
if($appPool)
{
if($stop)
{
$appPool.Stop()
}
else
{
$appPool.Start()
}
}
If anybody is looking for a purely command-line tool that does not require Powershell, I have created such a thing based on the information contained in these other answers. Since the original question is specifically looking for possible command-line alternatives, I thought I would share it here.
Usage is quite simple:
IIS6AppPool Start DefaultAppPool
IIS6AppPool Stop AppPool #1
IIS6AppPool Recycle Some other app pool
Source and binaries are available on bitbucket. May this save somebody else a few minutes of head scratching.
You might be interested in this Powershell library I started maintaining:
psDeploy : http://rprieto.github.com/psDeploy/
Among other things it has lots of cmdlets for IIS6 automation, for example Start-IIS6AppPool, New-IIS6Website...
I hope it helps!
If on Windows Server 2003 it is simpler to use the supplied script iisapp.vbs
CScript.exe C:\WINDOWS\system32\iisapp.vbs /?
CScript.exe C:\WINDOWS\system32\iisapp.vbs /a MyApp /r
Or depending on your setup (default to Cscript not WScript), simply
iisapp /a MyApp /r
And of course it is different in IIS7
If you wish to do this remotely, and / or on a machine without powershell you can modify the script posted here.
It uses WMI to access and recycle the app pool, from VBScript. It's a trivial change to make it stop / start pools instead of recycling them, you just need to call .Stop or .Start on the app pool in question.
The meat of the script is paraphrased below:
strServer = "LocalHost" 'Server name goes here
strAppPoolName = "MyAppPool" 'App pool name goes here
'Connect to the specified server using WMI
set Locator = CreateObject("WbemScripting.SWbemLocator")
Locator.Security_.AuthenticationLevel = 6
set Service = locator.connectserver(strServer,"root/MicrosoftIISv2")
'Get a collection of WMI apppools
set APCollection = Service.InstancesOf("IISApplicationPool")
For each APInstance in APCollection
If UCase(ApInstance.Name) = UCase("W3SVC/AppPools/" & strAppPoolName) Then
WScript.Echo "Recycling " & strServer & "/" & APInstance.Name
' You can do any of these things depending you what you want to do.
APInstance.Recycle
APInstance.Stop
APInstance.Start
End If
Next
If you have some kind of command line / batch toolchain which you want to integrate this into, you can execute a VBScript file in command line mode by calling:
CScript.exe \NoLogo MyScriptFile.vbs
The \NoLogo switch removes the VBScript interpreter startup messages and running it with CScript.exe means that calls to WScript.Echo go to the command line rather than a popup window.
You could create a function to stop or start the application pool remotely as below:
function StopOrStartAppPool($RemoteServerName, $AppPoolName, $commandWebPool)
{
if ($commandWebPool -eq "Stop")
{
$wmiprocess = [wmiclass]"\\$RemoteServerName\root\cimv2:win32_process"
$wmiprocess.create("cscript.exe C:\Inetpub\AdminScripts\adsutil.vbs STOP_SERVER W3SVC/AppPools/$AppPoolName -s:$RemoteServerName")
}
else
{
$wmiprocess = [wmiclass] "\\$RemoteServerName\root\cimv2:win32_process"
$wmiprocess.create("cscript.exe C:\Inetpub\AdminScripts\adsutil.vbs START_SERVER W3SVC/AppPools/$AppPoolName -s:$RemoteServerName")
}
}