I'm using a PowerShell script that creates local share folder.
function shareCacheFolder() {
$Sharename = 'cacheFolder'
$Foldername = 'c:\cacheFolder'
if (!(Get-WmiObject Win32_Share -Filter "name='$Sharename'")) {
$Shares = [WMICLASS]"Win32_Share"
$Shares.Create($Foldername, $Sharename, 0)
}
}
This seems to work on most machines. But not on mine.
I'm getting this output:
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 8
PSComputerName :
I've also tried using this convention:
function shareCacheFolder() {
$path = "c:\cachefolder"
$name = "cachefolder"
$type = 0
$password = ""
$description = ""
$max = 100
$access = $null
if (!(Get-WmiObject Win32_Share -Filter "name='$Sharename'")) {
Invoke-WmiMethod -Class Win32_Share -Name Create -ArgumentList $access, $description, $max, $name, $password, $path, $type
}
}
I'm using PowerShell version 3.
As documented the return code 8 means "unknown error". The command is syntactically correct and works on other computers, so the issue is not with your code. The problem is also unlikely to be caused by a share name conflict, missing folder, permission issue, etc., as those would cause different errors/return codes.
I suspect that on your system the Server service is not running. Verify that with the following command:
Get-Service 'Server' | Select-Object StartType, Status | Format-List
The start type should be "Automatic", and the status should be "Running". If they're not, change the start type and start the service like this:
Get-Service 'Server' | Set-Service -StartupType 'Automatic'
Start-Service 'Server'
Related
I'm struggling to create a WQL query for SCCM as I'm really new and rarely use it in a complex manner.
My goal is to list 3 things : Computer name - Display Name ("Google Chrome") - Display Version (of that Google Chrome entry)
I'm starting with this :
$SiteCode = "XXX"
$SiteServer = "XXX"
$query = #"
select SMS_R_System.Name, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
from SMS_R_System
inner join SMS_G_System_ADD_REMOVE_PROGRAMS
on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
where SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName = "Google Chrome"
"#
Get-WmiObject -namespace root\sms\site_$SiteCode -computer $SiteServer -query $query
The output is a bit strange to me :
__GENUS : 2
__CLASS : __GENERIC
__SUPERCLASS :
__DYNASTY : __GENERIC
__RELPATH :
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER : XXX
__NAMESPACE : root\sms\site_PR1
__PATH :
SMS_G_System_ADD_REMOVE_PROGRAMS : System.Management.ManagementBaseObject
SMS_R_System : System.Management.ManagementBaseObject
PSComputerName : XXX
What am I missing here? Again i'm really new at this so I must be missing a key part of the logic.
If I remove :
, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
The query works and shows me all the computers that have Chrome installed:
__GENUS : 2
__CLASS : SMS_R_System
__SUPERCLASS : SMS_Resource
__DYNASTY : SMS_BaseClass
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {SMS_Resource, SMS_BaseClass}
__SERVER : XXX
__NAMESPACE : root\sms\site_XXX
__PATH :
Name : PXXX
PSComputerName : XXX
but I want those 2 properties too, not just the computer name so I can confirm the version numbers.
Much appreciated.
To expand on my comments in an alternate way to handle the problem at hand:
$wmiParams = #{
Namespace = 'root/sms/site_XXX'
ComputerName = 'XXX'
Query = #'
SELECT SMS_R_System.Name, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
FROM SMS_R_System
INNER JOIN SMS_G_System_ADD_REMOVE_PROGRAMS
ON SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
WHERE SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName = "Google Chrome"
'#
}
$smsResults = Get-WmiObject #wmiParams
foreach ($object in $smsResults) {
[pscustomobject]#{
ComputerName = $object['SMS_R_System']['Name']
DisplayName = $object['SMS_G_System_ADD_REMOVE_PROGRAMS']['DisplayName']
Version = $object['SMS_G_System_ADD_REMOVE_PROGRAMS']['Version']
}
}
The answer is to simply "expand" the dictionaries like pointed out by #TheIncorrigible.
So here is how I ended up doing it using the Name/Expression method in Select-Object:
$query = #"
select SMS_R_System.Name, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
from SMS_R_System
inner join SMS_G_System_ADD_REMOVE_PROGRAMS
on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
where SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName = "Google Chrome"
"#
Get-WmiObject -namespace root\sms\site_$SiteCode -computer $SiteServer -query $query | Select-Object #{name='ComputerName';expression={$_.SMS_R_System.Name} }, #{name='DisplayName';expression={$_.SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName} }, #{name='Version';expression={$_.SMS_G_System_ADD_REMOVE_PROGRAMS.Version} }
I want change RDP port with WMI method but my code doesn't work and I don't know why.
Invoke-WmiMethod -Class StdRegprov -Name SetDWORDvalue -ArgumentList 2147483650,"System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp", "PortNumber", 3354
I get this after execute in PowerShell:
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 5
PSComputerName :
But nothing changed?
This right here indicates your problem:
ReturnValue : 5
Return code 5 means "access denied". Your user does not have permission to write to that registry location. You probably need to run the code "as administrator".
With that said, PowerShell provides direct access to the registry. You don't need WMI for that.
$reg = 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'
$name = 'PortNumber'
$value = 3354
New-ItemProperty -Path $reg -Name $name -Value $value -Type DWORD -Force | Out-Null
You still need to run this with a user who has write access to the registry key, though.
I'm using WMI to uninstall software remotely and it's working fine to remove the software. What I'm struggling with is using the results of that (Successful or not) to give a simple out put message rather than the normal output of the command. I normally use $lastexitcode for this but no matter whether or not the command succeeds it runs to my successful uninstall message. Here's what I'm trying to use:
$app = Get-WmiObject Win32_Product -ComputerName "$computer" | where { $_.vendor -eq "APN, LLC" }
$app.Uninstall()
if ($lastexitcode -eq 0)
{
write-host -ForegroundColor Green "Programm Successfully Removed"
}
else
{
write-host -ForegroundColor red "There was a problem uninstalling the program"
}
When I leave output of the operation on it returns:
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0
PSComputerName :
I figure I could do something with the ReturnValue but I'm not sure how. Any help would be greatly appreciated.
EDIT: The solution thanks to Bruce's answer:
$app = Get-WmiObject Win32_Product -ComputerName "$computer" | where { $_.vendor -eq "APN, LLC" }
$appuninstall = $app.Uninstall()
if ($appuninstall.returnvalue -eq 0)
{
write-host -ForegroundColor Green "Programm Successfully Removed"
}
else
{
write-host -ForegroundColor red "There was a problem uninstalling the program"
}
$LastExitCode is only set when running native commands (external .exes). In your code, you want to capture the result of the call to Uninstall() in a variable then use the return code property from that object in your if statement.
I am trying to subscribe to the event of a specific file being modified using WQL with this query:
SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA "CIM_DataFile" AND TargetInstance.Drive="C:" AND TargetInstace.Path="\\test\\filewatching\\"
I can register the event successfully (see output at the bottom) and can see it is bound with the script that I registered with (the consumer).
However, when I modify a file in C:\test\filewatching\ the script does not run.
Here is the code for registering for a File Creation Event in the same folder, and this works:
#WQL
$query = #"
SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA "Cim_DirectoryContainsFile" AND TargetInstance.GroupComponent="Win32_Directory.Name='C:\\test\\filewatching'"
"#
$instanceFilter = ([WMICLASS]"\\$Computername\root\subscription:__EventFilter").CreateInstance()
$instanceFilter.QueryLanguage = 'WQL'
$instanceFilter.Query = $query
$instanceFilter.Name = 'EventFilterNameHere'
$instanceFilter.EventNameSpace = 'root/CIMV2'
$result = $instanceFilter.Put()
# Consumer
$script =
#"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("c:\test\filewatching\Log.log", 8, True)
objFile.WriteLine "New File Created"
objFile.Close
"#
$instanceConsumer = ([wmiclass]"\\$Computername\root\subscription:ActiveScriptEventConsumer").CreateInstance()
$instanceConsumer.Name = 'ConsumerNameHere'
$instanceConsumer.ScriptingEngine = 'VBScript'
$instanceConsumer.ScriptFilename = ''
$instanceConsumer.ScriptText = $script
$instanceConsumer.Put()
# Binding
[object]$Filter = (Get-WMIObject -Computername $Computername -Namespace root\Subscription -Class __EventFilter | Sort Name)
[object]$Consumer = (Get-WMIObject -Computername $Computername -Namespace root\Subscription -Class __EventConsumer | Sort Name)
$instanceBinding = ([wmiclass]"\\$Computername\root\subscription:__FilterToConsumerBinding").CreateInstance()
$instanceBinding.Filter = $Filter
$instanceBinding.Consumer = $Consumer
$instanceBinding.Put()
So I know there is nothing wrong with my PowerShell. This makes me think that my query must be wrong.
I have tried a few tweaks of the above InstanceModificationEvent query, but with no success. (these tweaks include stuff like changing C: to C or removing \s from the TargetInstace.Path).
I need this subscription to be permanent and it can't reset if the PC is turned on or off - this is why I am using WQL. If anyone can suggest another way of achieving the same or how I can fix my query I will be eternally grateful!
Output after running the script:
Path : \\WIN7-IT3\root\subscription:ActiveScriptEventConsumer.Name="Co
nsumerNameHere"
RelativePath : ActiveScriptEventConsumer.Name="ConsumerNameHere"
Server : WIN7-IT3
NamespacePath : root\subscription
ClassName : ActiveScriptEventConsumer
IsClass : False
IsInstance : True
IsSingleton : False
Path : \\WIN7-IT3\root\subscription:__FilterToConsumerBinding.Consumer
="\\\\WIN7-IT3\\ROOT\\Subscription:ActiveScriptEventConsumer.Na
me=\"ConsumerNameHere\"",Filter="\\\\WIN7-IT3\\ROOT\\Subscripti
on:__EventFilter.Name=\"EventFilterNameHere\""
RelativePath : __FilterToConsumerBinding.Consumer="\\\\WIN7-IT3\\ROOT\\Subscri
ption:ActiveScriptEventConsumer.Name=\"ConsumerNameHere\"",Filt
er="\\\\WIN7-IT3\\ROOT\\Subscription:__EventFilter.Name=\"Event
FilterNameHere\""
Server : WIN7-IT3
NamespacePath : root\subscription
ClassName : __FilterToConsumerBinding
IsClass : False
IsInstance : True
IsSingleton : False
Querying WMI subscriptions:
Get-WmiObject -Namespace root\Subscription -Class __Eventfilter
Get-WMIObject -Namespace root\Subscription -Class __EventConsumer
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
Get-WMIObject -Namespace root\Subscription -Class ActiveScriptEventConsumer
Output after querying:
__GENUS : 2
__CLASS : __EventFilter
__SUPERCLASS : __IndicationRelated
__DYNASTY : __SystemClass
__RELPATH : __EventFilter.Name="EventFilterNameHere"
__PROPERTY_COUNT : 6
__DERIVATION : {__IndicationRelated, __SystemClass}
__SERVER : WIN7-IT3
__NAMESPACE : ROOT\Subscription
__PATH : \\WIN7-IT3\ROOT\Subscription:__EventFilter.Name="EventFilterNameHere"
CreatorSID : {1, 5, 0, 0...}
EventAccess :
EventNamespace : root/CIMV2
Name : EventFilterNameHere
Query : SELECT * FROM __InstanceModificationEvent WITHIN 5 WHERE TargetInstance ISA
"CIM_DataFile" AND TargetInstance.Drive="C:" AND
TargetInstace.Path="\\test\\filewatching\\"
QueryLanguage : WQL
PSComputerName : WIN7-IT3
__GENUS : 2
__CLASS : ActiveScriptEventConsumer
__SUPERCLASS : __EventConsumer
__DYNASTY : __SystemClass
__RELPATH : ActiveScriptEventConsumer.Name="ConsumerNameHere"
__PROPERTY_COUNT : 8
__DERIVATION : {__EventConsumer, __IndicationRelated, __SystemClass}
__SERVER : WIN7-IT3
__NAMESPACE : ROOT\Subscription
__PATH : \\WIN7-IT3\ROOT\Subscription:ActiveScriptEventConsumer.Name="ConsumerNameHere"
CreatorSID : {1, 5, 0, 0...}
KillTimeout : 0
MachineName :
MaximumQueueSize :
Name : ConsumerNameHere
ScriptFilename :
ScriptingEngine : VBScript
ScriptText : Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("c:\test\filewatching\Log.log", 8, True)
objFile.WriteLine "New File Created"
objFile.Close
PSComputerName : WIN7-IT3
__GENUS : 2
__CLASS : __FilterToConsumerBinding
__SUPERCLASS : __IndicationRelated
__DYNASTY : __SystemClass
__RELPATH : __FilterToConsumerBinding.Consumer="\\\\WIN7-IT3\\ROOT\\Subscription:ActiveS
criptEventConsumer.Name=\"ConsumerNameHere\"",Filter="\\\\WIN7-IT3\\ROOT\\Su
bscription:__EventFilter.Name=\"EventFilterNameHere\""
__PROPERTY_COUNT : 7
__DERIVATION : {__IndicationRelated, __SystemClass}
__SERVER : WIN7-IT3
__NAMESPACE : ROOT\Subscription
__PATH : \\WIN7-IT3\ROOT\Subscription:__FilterToConsumerBinding.Consumer="\\\\WIN7-IT
3\\ROOT\\Subscription:ActiveScriptEventConsumer.Name=\"ConsumerNameHere\"",F
ilter="\\\\WIN7-IT3\\ROOT\\Subscription:__EventFilter.Name=\"EventFilterName
Here\""
Consumer : \\WIN7-IT3\ROOT\Subscription:ActiveScriptEventConsumer.Name="ConsumerNameHer
e"
CreatorSID : {1, 5, 0, 0...}
DeliverSynchronously : False
DeliveryQoS :
Filter : \\WIN7-IT3\ROOT\Subscription:__EventFilter.Name="EventFilterNameHere"
MaintainSecurityContext : False
SlowDownProviders : False
PSComputerName : WIN7-IT3
__GENUS : 2
__CLASS : ActiveScriptEventConsumer
__SUPERCLASS : __EventConsumer
__DYNASTY : __SystemClass
__RELPATH : ActiveScriptEventConsumer.Name="ConsumerNameHere"
__PROPERTY_COUNT : 8
__DERIVATION : {__EventConsumer, __IndicationRelated, __SystemClass}
__SERVER : WIN7-IT3
__NAMESPACE : ROOT\Subscription
__PATH : \\WIN7-IT3\ROOT\Subscription:ActiveScriptEventConsumer.Name="ConsumerNameHere"
CreatorSID : {1, 5, 0, 0...}
KillTimeout : 0
MachineName :
MaximumQueueSize :
Name : ConsumerNameHere
ScriptFilename :
ScriptingEngine : VBScript
ScriptText : Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("c:\test\filewatching\Log.log", 8, True)
objFile.WriteLine "New File Created"
objFile.Close
PSComputerName : WIN7-IT3
Stumbled across this page soon after posting this question, from which I worked out that the query I need is:
SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'CIM_DataFile' AND TargetInstance.Name='c:\\test\\filewatching\\tester.txt'
Notice that contrary to several other posts online, what worked for me was actually to omit the Path and Drive parts of TargetInstance and only included the full path and name for the file I want to watch.
This works for me because I will only be watching 1 specific file. If you need to watch multiple files using this method you will need to register multiple subscriptions.
The full code for registering a File Modification watcher:
#WQL
$query = #"
SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'CIM_DataFile' AND TargetInstance.Name='c:\\test\\filewatching\\tester.txt'
"#
$instanceFilter = ([WMICLASS]"\\$Computername\root\subscription:__EventFilter").CreateInstance()
$instanceFilter.QueryLanguage = 'WQL'
$instanceFilter.Query = $query
$instanceFilter.Name = 'EventFilterNameHere'
$instanceFilter.EventNameSpace = 'root/CIMV2'
$result = $instanceFilter.Put()
# Consumer
$script =
#"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("c:\test\filewatching\Log.log", 8, True)
objFile.WriteLine "New File Created"
objFile.Close
"#
$instanceConsumer = ([wmiclass]"\\$Computername\root\subscription:ActiveScriptEventConsumer").CreateInstance()
$instanceConsumer.Name = 'ConsumerNameHere'
$instanceConsumer.ScriptingEngine = 'VBScript'
$instanceConsumer.ScriptFilename = ''
$instanceConsumer.ScriptText = $script
$instanceConsumer.Put()
# Binding
[object]$Filter = (Get-WMIObject -Computername $Computername -Namespace root\Subscription -Class __EventFilter | Sort Name)
[object]$Consumer = (Get-WMIObject -Computername $Computername -Namespace root\Subscription -Class __EventConsumer | Sort Name)
$instanceBinding = ([wmiclass]"\\$Computername\root\subscription:__FilterToConsumerBinding").CreateInstance()
$instanceBinding.Filter = $Filter
$instanceBinding.Consumer = $Consumer
$instanceBinding.Put()
you need to attach the path of the consumer and filter to the binder
instead of every filter\consumer in the system
$result = $instanceFilter.Put()
$filterPath = $result.Path
$result = $instanceConsumer.Put()
$consumerPath = $result.Path
$bind.Filter = $filterPath
$bind.Consumer = $consumerPath
I'm trying to write a script which uninstalls Microsoft Office 2007 Enterprise by grabbing the IdentifyingNumber using Get-WmiObject -Class Win32_Product. I'm able to grab the IdentifyingNumber, but when I attempt to uninstall PowerShell outputs some information that I'm not sure what to do with. Is this not a proper way to utilize Uninstall()?
$2k7 = Get-WmiObject -Class Win32_Product | Where-Object { $_.IdentifyingNumber -match "{90120000-0030-0000-0000-0000000FF1CE}" }
if ($2k7 -ne $null) {
$2k7.Uninstall()
}
else {
write-host "nothing to see here"
}
Output...
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 1603
Error 1603 is a catch-all error used by Microsoft Installer when an unexpected failure is encountered.
I would verify that you're running your Powershell window with elevated privileges and that the program you intend to uninstall doesn't have any processes currently running.