I'm trying to mount a couple of network drives and then rename them. However my Powershell script is failing after the first drive renames fine. For the second one I get an error:
Exception calling "Put" with "0" argument(s): ""
At C:\Users\ben\Documents\mapdrives.ps1:12 char:11
+ $disk.Put <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
My script looks like this:
cls
$Username = ""
$Password = ""
$net = New-Object -com WScript.Network;
$Drive = "M:"
$UNC = "\\server01\bin$"
$net.mapnetworkdrive($Drive, $Unc, $false, $Username, $Password)
$disk = Get-WmiObject "Win32_LogicalDisk WHERE DeviceID='M:'"
if (-not $disk) { return }
$disk.VolumeName = "server1_bin"
$disk.Put()
$Drive = "N:"
$UNC = "\\server01\data$"
$net.mapnetworkdrive($Drive, $Unc, $false, $Username, $Password)
$disk = Get-WmiObject "Win32_LogicalDisk WHERE DeviceID='N:'"
if (-not $disk) { return }
$disk.VolumeName = "server1_data"
$disk.Put()
What am I doing wrong?
Try Like this using comobject for label a drive:
$a = New-Object -ComObject shell.application
$a.NameSpace( "M:\" ).self.name = "server1_bin"
in any case you need run the console as a user with administrative rigth
I have written powershell script
function ChangeDriveLabel([string]$driveletter,[string]$newlabel )
{
$disk = Get-WmiObject -Class win32_volume -Filter "DriveLetter = '$driveletter'"
Set-WmiInstance -input $disk -Arguments #{ Label=$newlabel}
}
ChangeDriveLabel -driveletter 'e:' -newlabel 'DBLOG'
you can also just run this at the prompt
label c: OS
to change the drive label to "OS"
label d: Data
to change the drive label to "Data"
To confirm then run diskpart to activate disk partition and then the command list volume at the diskpart prompt to show volumes and their names
Related
I was looking for a solution to pin a shortcut or program to the task in win 10 with PS. I found Pin program to taskbar using PS in Windows 10. The VB Script works,
If WScript.Arguments.Count < 1 Then WScript.Quit
'----------------------------------------------------------------------
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFile = WScript.Arguments.Item(0)
sKey1 = "HKCU\Software\Classes\*\shell\{:}\\"
sKey2 = Replace(sKey1, "\\", "\ExplorerCommandHandler")
'----------------------------------------------------------------------
With WScript.CreateObject("WScript.Shell")
KeyValue = .RegRead("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" & _
"\CommandStore\shell\Windows.taskbarpin\ExplorerCommandHandler")
.RegWrite sKey2, KeyValue, "REG_SZ"
With WScript.CreateObject("Shell.Application")
With .Namespace(objFSO.GetParentFolderName(objFile))
With .ParseName(objFSO.GetFileName(objFile))
.InvokeVerb("{:}")
End With
End With
End With
.Run("Reg.exe delete """ & Replace(sKey1, "\\", "") & """ /F"), 0, True
End With
'----------------------------------------------------------------------
I can invoke VB script from PS but a helpful person converted the script to PS
Param($Target)
$KeyPath1 = "HKCU:\SOFTWARE\Classes"
$KeyPath2 = "*"
$KeyPath3 = "shell"
$KeyPath4 = "{:}"
$ValueName = "ExplorerCommandHandler"
$ValueData =
(Get-ItemProperty `
("HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\" + `
"CommandStore\shell\Windows.taskbarpin")
).ExplorerCommandHandler
$Key2 = (Get-Item $KeyPath1).OpenSubKey($KeyPath2, $true)
$Key3 = $Key2.CreateSubKey($KeyPath3, $true)
$Key4 = $Key3.CreateSubKey($KeyPath4, $true)
$Key4.SetValue($ValueName, $ValueData)
$Shell = New-Object -ComObject "Shell.Application"
$Folder = $Shell.Namespace((Get-Item $Target).DirectoryName)
$Item = $Folder.ParseName((Get-Item $Target).Name)
$Item.InvokeVerb("{:}")
$Key3.DeleteSubKey($KeyPath4)
if ($Key3.SubKeyCount -eq 0 -and $Key3.ValueCount -eq 0) {
$Key2.DeleteSubKey($KeyPath3)
}
However this PS script will not run unless the VB script has been ran at least one time. Is there a way to make the PS script work without having to run the VB script?
The error I get when trying to run the PS script without running the VB script at least once before it:
You cannot call a method on a null-valued expression.
At \\server\Utilities\TaskbarPin.ps1:41 char:5
+ $Key3 = $Key2.CreateSubKey($KeyPath3, $true)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At \\server\Utilities\TaskbarPin.ps1:42 char:5
+ $Key4 = $Key3.CreateSubKey($KeyPath4, $true)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At \\server\Utilities\TaskbarPin.ps1:43 char:5
+ $Key4.SetValue($KeyValue, $ValueData)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At \\server\Utilities\TaskbarPin.ps1:50 char:5
+ $Key3.DeleteSubKey($KeyPath4)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
I do not get an error after using the VB script once to do the task.
You should not have been impacted by this this way.
The code works as designed, but you have to call the path the exe fully.
I just converted it to a function and it is successful with no other dependencies.
Function Add-AppToTaskbar
{
[cmdletbinding()]
Param
(
[string]$Target
)
$KeyPath1 = "HKCU:\SOFTWARE\Classes"
$KeyPath2 = "*"
$KeyPath3 = "shell"
$KeyPath4 = "{:}"
$ValueName = "ExplorerCommandHandler"
$ValueData =
(Get-ItemProperty `
("HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\" + `
"CommandStore\shell\Windows.taskbarpin")
).ExplorerCommandHandler
$Key2 = (Get-Item $KeyPath1).OpenSubKey($KeyPath2, $true)
$Key3 = $Key2.CreateSubKey($KeyPath3, $true)
$Key4 = $Key3.CreateSubKey($KeyPath4, $true)
$Key4.SetValue($ValueName, $ValueData)
$Shell = New-Object -ComObject "Shell.Application"
$Folder = $Shell.Namespace((Get-Item $Target).DirectoryName)
$Item = $Folder.ParseName((Get-Item $Target).Name)
$Item.InvokeVerb("{:}")
$Key3.DeleteSubKey($KeyPath4)
if ($Key3.SubKeyCount -eq 0 -and $Key3.ValueCount -eq 0)
{$Key2.DeleteSubKey($KeyPath3)}
}
Add-AppToTaskbar -Target 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
BTW, these pinned things live in two places on your system:
Here:
$env:USERPROFILE\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
Registry:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband
Both are required.
Update based on OP's comment
I just ran this locally and remotely, both are successful. See results below.
The local host I am using - WS2012R2 set as a workstation role
I don't have any W10 systems in my lab. The earlier test was on a local W10 host.
Executed in the console host, ISE and VSCode.
PS C:\Windows\system32> $env:COMPUTERNAME
LabWS01
# PS Version
PS C:\Windows\system32> $PSVersionTable
Name Value
---- -----
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.42000
BuildVersion 6.3.9600.18968
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
# the current user profile pinned location filtered for notepad*
PS C:\Windows\system32> Get-ChildItem -Path "$env:USERPROFILE\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Notepad*"
# Tested path to remote share
PS C:\Windows\system32> Test-path -Path '\\Server\ShareName\Add-AppToTaskbar.ps1'
True
# Ran the script from that remote share
PS C:\Windows\system32> \\Server\ShareName\Add-AppToTaskbar.ps1 'c:\windows\notepad.exe'
or this way...
Start-process -FilePath Powershell -ArgumentList '\\Server\ShareName\Add-AppToTaskbar.ps1 -Target C:\Windows\notepad.exe'
# Review pinned item location, filtered for notepad*
PS C:\Windows\system32> Get-ChildItem -Path "$env:USERPROFILE\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Notepad*"
Directory: C:\Users\Labuser001\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 8/9/2018 8:48 PM 791 Notepad.lnk
Shortcut shows pinned to taskbar.
So, this sounds environmental on your side. Now you can pin apps using GPO if this issue continues.
I've modified your function so that selectively pins or unpins items to the taskbar. Previously, the problem is that the pin command was not exclusive, it would unpin the application if it was already pinned. With further detection of what was pinned in a binary registry value, it has been possible to determine that the item has already been pinned and it will not attempt to pin the item twice.
Set-AppPinTaskbarCsv is a function that was customized for our environment, I only include it as an example only, if someone wanted to roll this out in a login script to ensure the users have all of the apps they need pinned, it would need a good deal of modification and simplification. It has some functions which are not included that check group membership and reformat strings to expand variables, which are not required. After pinning the applications, it displays more reliably if explorer is restarted, and the Csv function will restart explorer if any items are pinned.
Function Set-PinTaskbar {
Param (
[parameter(Mandatory=$True, HelpMessage="Target item to pin")]
[ValidateNotNullOrEmpty()]
[string] $Target
,
[Parameter(Mandatory=$False, HelpMessage="Target item to unpin")]
[switch]$Unpin
)
If (!(Test-Path $Target)) {
Write-Warning "$Target does not exist"
Break
}
$Reg = #{}
$Reg.Key1 = "*"
$Reg.Key2 = "shell"
$Reg.Key3 = "{:}"
$Reg.Value = "ExplorerCommandHandler"
$Reg.Data = (Get-ItemProperty ("HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.taskbarpin")).ExplorerCommandHandler
$Reg.Path1 = "HKCU:\SOFTWARE\Classes"
$Reg.Path2 = Join-Path $Reg.Path1 $Reg.Key1
$Reg.Path3 = Join-Path $Reg.Path2 $Reg.Key2
$Reg.Path4 = Join-Path $Reg.Path3 $Reg.Key3
If (!(Test-Path -LiteralPath $Reg.Path2)) {
New-Item -ItemType Directory -Path $Reg.Path1 -Name [System.Management.Automation.WildcardPattern]::Escape($Reg.Key1)
}
If (!(Test-Path -LiteralPath $Reg.Path3)) {
New-Item -ItemType Directory -Path ([System.Management.Automation.WildcardPattern]::Escape($Reg.Path2)) -Name $Reg.Key2
}
If (!(Test-Path -LiteralPath $Reg.Path4)) {
New-Item -ItemType Directory -Path ([System.Management.Automation.WildcardPattern]::Escape($Reg.Path3)) -Name $Reg.Key3
}
Set-ItemProperty -Path ([System.Management.Automation.WildcardPattern]::Escape($Reg.Path4)) -Name $Reg.Value -Value $Reg.Data
$Shell = New-Object -ComObject "Shell.Application"
$Folder = $Shell.Namespace((Get-Item $Target).DirectoryName)
$Item = $Folder.ParseName((Get-Item $Target).Name)
# Registry key where the pinned items are located
$RegistryKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband"
# Binary registry value where the pinned items are located
$RegistryValue = "FavoritesResolve"
# Gets the contents into an ASCII format
$CurrentPinsProperty = ([system.text.encoding]::ASCII.GetString((Get-ItemProperty -Path $RegistryKey -Name $RegistryValue | Select-Object -ExpandProperty $RegistryValue)))
# Filters the results for only the characters that we are looking for, so that the search will function
[string]$CurrentPinsResults = $CurrentPinsProperty -Replace '[^\x20-\x2f^\x30-\x3a\x41-\x5c\x61-\x7F]+', ''
# Globally Unique Identifiers for common system folders, to replace in the pin results
$Guid = #{}
$Guid.FOLDERID_ProgramFilesX86 = #{
"ID" = "{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}"
"Path" = ${env:ProgramFiles(x86)}
}
$Guid.FOLDERID_ProgramFilesX64 = #{
"ID" = "{6D809377-6AF0-444b-8957-A3773F02200E}"
"Path" = $env:ProgramFiles
}
$Guid.FOLDERID_ProgramFiles = #{
"ID" = "{905e63b6-c1bf-494e-b29c-65b732d3d21a}"
"Path" = $env:ProgramFiles
}
$Guid.FOLDERID_System = #{
"ID" = "{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}"
"Path" = Join-Path $env:WINDIR "System32"
}
$Guid.FOLDERID_Windows = #{
"ID" = "{F38BF404-1D43-42F2-9305-67DE0B28FC23}"
"Path" = $env:WINDIR
}
ForEach ($GuidEntry in $Guid.Keys) {
$CurrentPinsResults = $CurrentPinsResults -replace $Guid.$GuidEntry.ID,$Guid.$GuidEntry.Path
}
$Split = $CurrentPinsResults -split ('C:')
$SplitOutput = #()
# Process each path entry, remove invalid characters, test to determine if the path is valid
ForEach ($Entry in $Split) {
If ($Entry.Substring(0,1) -eq '\') {
# Get a list of invalid path characters
$InvalidPathCharsRegEx = [IO.Path]::GetInvalidPathChars() -join ''
$InvalidPathChars = "[{0}]" -f [RegEx]::Escape($InvalidPathCharsRegEx)
$EntryProcessedPhase1 = "C:" + ($Entry -replace $InvalidPathChars)
$EntryProcessedPhase2 = $null
# Remove characters from the path until it is resolvable
ForEach ($Position in $EntryProcessedPhase1.Length .. 1) {
If (Test-Path $EntryProcessedPhase1.Substring(0,$Position)) {
$EntryProcessedPhase2 = $EntryProcessedPhase1.Substring(0,$Position)
Break
}
}
# If the path resolves, add it to the array of paths
If ($EntryProcessedPhase2) {
$SplitOutput += $EntryProcessedPhase2
}
}
}
$PinnedItems = #()
$Shell = New-Object -ComObject WScript.Shell
ForEach ($Path in $SplitOutput) {
# Determines if the entry in the registry is a link in the standard folder, if it is, resolve the path of the shortcut and add it to the array of pinnned items
If ((Split-Path $Path) -eq (Join-Path $env:USERPROFILE "AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar")) {
$Shell.CreateShortcut($Path).TargetPath
$PinnedItems += $Shell.CreateShortcut($Path).TargetPath
}
Else {
# If the link or executable is not in the taskbar folder, add it directly
$PinnedItems += $Path
}
}
# Unpin if the application is pinned
If ($Unpin.IsPresent) {
If ($PinnedItems -contains $Target) {
$Item.InvokeVerb("{:}")
Write-Host "Unpinning application $Target"
}
}
Else {
# Only pin the application if it hasn't been pinned
If ($PinnedItems -notcontains $Target) {
$Item.InvokeVerb("{:}")
Write-Host "Pinning application $Target"
}
}
# Remove the registry key and subkeys required to pin the application
If (Test-Path $Reg.Path3) {
Remove-Item -LiteralPath $Reg.Path3 -Recurse
}
}
Function Set-PinTaskbarCsv {
Param (
[Parameter(Mandatory=$true)]
$PinHashTable
,
[Parameter(Mandatory=$true)]
$UnpinHashTable
)
$Organization = "LIHC"
$RootRegistry = "HKCU:\Software\" + $Organization
$RootRegistryPinned = Join-Path $RootRegistry "Pinned"
# Unpin applications from taskbar
ForEach ($Entry in $UnpinHashTable.Keys) {
$Location = Format-VariablesString -String $UnpinHashTable.$Entry.Location
Add-Log "Taskbar app unpinned" $Location
Set-PinTaskbar -Target $Location -Unpin
}
# Pin applications to taskbar
$Groups = #("Group1","Group2","Group3","Group4","Group5")
ForEach ($Entry in $PinHashTable.Keys) {
$Entry
$Location = Format-VariablesString -String $PinHashTable.$Entry.Location
$ToTaskbar = [string]::IsNullOrWhiteSpace($PinHashTable.$Entry.Group1)
ForEach ($Group in $Groups) {
If (!([string]::IsNullOrWhiteSpace($PinHashTable.$Entry.$Group))) {
$ToTaskbar = (Get-UserGroups -Username $env:USERNAME -Group $PinHashTable.$Entry.$Group) -or $ToTaskbar
}
}
If (!([string]::IsNullOrWhiteSpace($PinHashTable.$Entry.TestPath))) {
$ToTaskbar = ((Test-Path $PinHashTable.$Entry.TestPath) -or (Test-Path $PinHashTable.$Entry.TestPath2)) -and $true
}
If ($ToTaskbar -and (Test-Path $Location) -and (!(Get-ItemProperty $RootRegistryPinned $Location -ErrorAction SilentlyContinue))) {
#Set-AppPinTaskbar -Application $Location
Set-PinTaskbar -Target $Location
Add-Log "Taskbar app Pinned" $Location
New-ItemProperty -Path $RootRegistryPinned -Name $Location 2>&1 > $null
$Status = $true
}
}
If ($Status) {
Get-Process -Name explorer | Stop-Process
Start-Process -FilePath explorer.exe
}
}
I am running Powershell on a remote computer that is not connected to the domain, does not have any modules and is running PS 2.0.
I want to contact the Active Directory of my domain, check if there is an entry for this computer and; if yes, delete that entry.
Checking the AD via ADSI for existance of the computer is easy. However the deleting does not work somehow.
Here is my code so far:
# Variables
$domain = "Test.com"
$Ldap = "LDAP://$domain"
$Global:AdsiSearcher = $Null
# Function to Delete PC
Function DeleteThisPc ()
{
$CurrentSearch = $Global:AdsiSearcher
$One = $CurrentSearch.FindOne()
$OPath = [adsi]$One.Path
$OPath.psbase.DeleteTree()
The Problem lies here. Even though $OPath is of type System.DirectoryServices.DirectoryEntry and the propertylist shows all properties, it does not allow me to delete the object.
Exception calling "DeleteTree" with "0" argument(s): "Logon failure:
unknown user name or bad password.
At C:\TEMP\Domjoin1.1.ps1:49 char:33 $OPath.psbase.DeleteTree <<<< ()
CategoryInfo: NotSpecified: (:) [], MethodInvocationException
FullyQualifiedErrorId : DotNetMethodException
Code:
# Function to get a ADSISearcher and set it to the global-AdsiSearcher
Function ConnectAD ()
{
$domain = new-object DirectoryServices.DirectoryEntry($Ldap,"$domain\Bob",'1234')
$filter = "(&(objectCategory=computer)(objectClass=computer)(cn=$ComputerName))"
$AdsiSearch = [adsisearcher]""
$AdsiSearch.SearchRoot = $domain
$AdsiSearch.Filter = $filter
$Global:AdsiSearcher = $AdsiSearch
}
# Main Function
Function Sub_Check-ADComputer()
{
ConnectAD
$CurSearch = $Global:AdsiSearcher.findOne()
if($CurSearch -ne $null)
{
DeleteThisPc
}
}
# Start
Sub_Check-ADComputer
Even though the issue seems to be obvious as the error states:
Logon failure: unknown user name or bad password.
The username and password is the same that I use to get the object from the AD in the first place. So it does work - do I somehow have to give the credentials again when trying to deleteTree() ? I also gave the User FullControl on the OU that the object is stored in.
Edit:
When I do it on another machine with PS 3.0 I get a different Error message:
Exception calling "DeleteTree" with "0" argument(s): "Access is
denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
I found the problem.
When using invoke command the variables are not transmitted unless specified by -argumentlist. Another approach I discovered was the following, which is the one I am using now and which works like a charm.
$domain = "DOMAINNAME"
$AdUser = "$domain\JoinDom"
$AdPW = "PASSWORD"
$AdPass = convertto-securestring -string $AdPW -AsPlainText -Force
$AdCred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdUser,$AdPass
$ThisComputer = $Env:COMPUTERNAME
$RetValue = $true
Function CheckExist ()
{
$ErrorActionPreference = ‘SilentlyContinue’
$Ascriptblock = $ExecutionContext.InvokeCommand.NewScriptBlock("get-adcomputer $ThisComputer")
$Ret = Invoke-Command -ComputerName SERVERNAME -ScriptBlock $Ascriptblock -Credential $AdCred
$ErrorActionPreference = ‘Continue’
return $Ret
}
$ExistBefore = CheckExist
if($ExistBefore -ne $null)
{
$scriptblock = $ExecutionContext.InvokeCommand.NewScriptBlock("Remove-ADComputer $ThisComputer")
Invoke-Command -ComputerName SERVERNAME -ScriptBlock $scriptblock -Credential $AdCred
$ExistAfter = CheckExist
if($ExistAfter -ne $null){$RetValue = $false}
}
if($RetValue -ne $false)
{
Add-computer -domainname $domain -credential $Adcred -OUPath "OU=MyOU,DC=DOMAIN,DC=DE"
Restart-Computer -Force
}
If your domain controller runs Windows Server 2008 or higher you could leverage PowerShell sessions to avoid having to work with ADSI.
Just run the following command:
Enter-PSSession -ComputerName domaincontroller.test.com -Credential (Get-Credential)
Then run Import-Module ActiveDirectory to allow you to use Get-ADComputer and Remove-ADComputer.
When using the below code to create printer on Windows 2008 servers to create the printers
`function CreatePrinterPort {
$server = $args[0]
$port = ([WMICLASS]“\\$server\ROOT\cimv2:Win32_TCPIPPrinterPort").createInstance()
$port.Name= $args[1]
$port.SNMPEnabled=$false
$port.Protocol=2
$port.HostAddress= $args[2]
$port.Put()
}
function CreatePrinter {
$server = $args[0]
$print = ([WMICLASS]“\\$server\ROOT\cimv2:Win32_Printer”).createInstance()
$print.Drivername = $args[1]
$print.PortName = $args[2]
$print.Shared = $true
$print.Published = $false
$print.Sharename = $args[3]
$print.Location = $args[4]
$print.Comment = $args[5]
$print.DeviceID=$args[2]
$print.Put()
}
$printers = Import-Csv “C:\printers.csv”
foreach ($printer in $printers) {
CreatePrinterPort $printer.Printserver $printer.Portname $printer.IPAddress
CreatePrinter $printer.Printserver $printer.Driver $printer.Portname $printer.Sharename $printer.Location $printer.Comment $printer.Printername
}'
I am getting the following error. The port creation function is working.
"IsSingleton : False
Exception calling "Put" with "0" argument(s): "Generic failure "
At line:23 char:1
+ $print.Put()
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException"
I have importing all the details from a CSV file and it contains all the information.
Any suggestions?
I'm pretty sure you're both doing this the hard way, and didn't read the MSDN page for the Win32_Printer class. It says in the remarks that you have to enable the SeDriverUpdate privilege before you can issue the Put method, so I have a feeling that's where you're getting your error from.
Next, use the Set-WMIInstance cmdlet, or the newer 'New-CIMInstance` if you can. Calling the classes directly is possible I'm sure, but if the server is local it won't enable the privileges that you need to create a printer.
Lastly, you could make your function better if you made it an advanced function, and allowed piped data. Check this out:
function CreatePrinter {
[cmdletbinding()]
Param(
[Parameter(ValueFromPipelineByPropertyName=$true)]
[Alias('Printserver')]
$Server,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[Alias('Driver')]
$Drivername,
[Parameter(ValueFromPipelineByPropertyName=$true)]
$PortName,
[Parameter(ValueFromPipelineByPropertyName=$true)]
$Sharename,
[Parameter(ValueFromPipelineByPropertyName=$true)]
$Location,
[Parameter(ValueFromPipelineByPropertyName=$true)]
$Comment,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[Alias('IPAddress')]
$HostAddress,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[Alias('PrinterName')]
$Name
)
PROCESS{
$PortArgs = #{
Name = $PortName
SNMPEnabled = $false
Protocol = 2
HostAddress = $HostAddress
}
Set-WmiInstance -Class Win32_TCPIPPrinterPort -Arguments $PortArgs -ComputerName $Server -PutType UpdateOrCreate -EnableAllPrivileges
$PrinterArgs = #{
Drivername = $Drivername
PortName = $PortName
Shared = $true
Published = $false
Sharename = $Sharename
Location = $Location
Comment = $Comment
DeviceID = $PortName
Name = $Name
}
Set-WmiInstance -Class Win32_Printer -Arguments $CmdArgs -ComputerName $Server -PutType UpdateOrCreate -EnableAllPrivileges
}
}
That creates the port, and then the printer. I suppose you could split it into two functions, but do you really see needing one without the other? Plus you can pipe your CSV data directly into it like this:
Import-CSV "C:\printers.csv" | CreatePrinter
That's it, that will create ports and printers for all records in the CSV. Plus I used the UpdateOrCreate enum, so if something isn't right you could correct the CSV and just run it again to refresh the settings to the correct settings without having to worry about deleting old copies and making new copies of things.
I have a script which I think is most of the way to being able to grab IE history for all of the users on a machine. My problem is it doesn't work for users other than myself because I get a permissions error when attempting open the folder. Does anyone have any ideas how I can fix the permissions problem?
I'm running this script on a Windows 2012r2 machine and I am an administrator on the box.
Thanks!
function Get-History
{
param
(
[string]$userName
)
$shell = New-Object -ComObject Shell.Application
if($username)
{
$users = $username
}
else
{
$users = Get-ChildItem C:\Users
}
if((([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")))
{
Foreach($user in $users)
{
$user = Split-Path $user -leaf
try
{
$ErrorActionPreference = 'Stop'
$hist = $shell.NameSpace("C:\Users\$user\AppData\Local\Microsoft\Windows\History")
}
catch
{
continue
}
$folder = $hist.Self
#$folder.Path
if($hist){
$hist.Items() | foreach {
#""; ""; $_.Name
if ($_.IsFolder) {
$siteFolder = $_.GetFolder
$siteFolder.Items() | foreach {
$site = $_
#""; $site.Name
if ($site.IsFolder) {
$pageFolder = $site.GetFolder
$pageFolder.Items() | foreach {
$url = $pageFolder.GetDetailsOf($_,0)
$date = $pageFolder.GetDetailsOf($_,2)
#"$user`: $date visited $url"
#Write-Output ("$user,$date,`"$url`"" | ConvertFrom-Csv)
New-Object -TypeName PSObject -Property #{
user=$user;
date = $date;
url = $url
}
}
}
}
}
}
}
}
}
else
{
Write-Host "Not Admin"
}
}
If I run just the small snippet:
$shell = New-Object -ComObject Shell.Application
$hist = $shell.NameSpace("C:\Users\MyOwnUsername\AppData\Local\Microsoft\Windows\History")
Then I successfully assign the $hist variable as a System.__ComObject
But if I run:
$shell = New-Object -ComObject Shell.Application
$hist = $shell.NameSpace("C:\Users\SomeOtherUser\AppData\Local\Microsoft\Windows\History")
I get:
Exception calling "NameSpace" with "1" argument(s): "Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))"
At line:3 char:1
+ $hist = $shell.NameSpace("C:\Users\SomeOtherUser\AppData\Local\Microsoft\Windows\History ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
Full Disclosure: it's a slight modification of the script at this blog post
I never solved the permissions problem. I changed strategy to use BrowsingHistoryViewer by Nirsoft.
$execPath = "C:\BrowsingHistoryView.exe"
$computers = 'computer1','computer2','computer3','computer4'
$outPath = "c:\"
$computers |
ForEach-Object{ `
Start-Process $execPath `
-argumentList "/HistorySource 3",
"/HistorySourceFolder ""\\$_\c$\Users""",
"/scomma ""$outpath\history_$_.txt"""
}
I am running in a lab environment and need to automate about 50 machines. I am trying to recover an .xml wireless network profile from a server then install it. This command is being sent from 1 server to the 50 clients.
I recently reimaged my some of my clients and upgraded from PS2 to PS3 and now my Download script is not working anymore.
It does work fine on my PS2 workstations. I am assuming that it might be a permission thing, but I'm not sure. ThrustedHosts is set to * and Script execution policy is set to Unrestricted.
Here's a snippet and the error:
function InstallProfile(){
clear
$fonction =
#'
param($profileName)
$File = "c:\profiles\profile.xml"
$webclient = New-Object System.Net.WebClient
$webclient.Proxy = $NULL
$ftp = "ftp://anonymous:anonymous#192.168.2.200/profiles/$profileName"
$uri = New-Object System.Uri($ftp)
Write-Host (hostname)
$webclient.DownloadFile($uri, $File)
write-host (hostname) (netsh wlan add profile filename="c:\profiles\profile.xml")
'#
$profileName = Read-Host "Enter the profile name(XML file must be present in c:\share\profiles\)"
ExecCmd -fonction $fonction -argument $profileName
func_done
}
#
function ExecCmd
{
param(
$fonction,
$argument
)
$PingTest = RetrieveStatus
$results = #{}
$results = $PingTest.up
$results | sort -uniq | out-Null
$fonctionSB = ConvertTo-ScriptBlock($fonction)
foreach($result in $results)
{
$os = "Windows"
try{
$session = New-PSSession -ComputerName $result.address -Credential $credentials -EA stop
}
catch{
$os = "Not Windows"
}
if($os -eq "Windows"){
Invoke-Command $result.address -ScriptBlock $fonctionSB -Arg $argument -Credential $credentials
Get-PSSession | Remove-PSSession
}
else{
Write-Host $result.address "does not support Powershell commands"
}
}
}
And the error:
Exception calling "DownloadFile" with "2" argument(s): "An exception occurred during a WebClient request."
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
+ PSComputerName : 192.168.2.110
I found a workaround,
I added a try/catch for the webclient.Download, which works for PS2. In the catch portion, I replaced the command with Invoke-WebRequest $uri -OutFile $File
Works fine for PS2 and PS3 this way!