Invoke .exe file with keys, which was copied via PowerShell - powershell

I try execute .exe file which was copied from network folder to host folder with keys for silent installation by using this script:
Get-ChildItem "D:\" -Filter *.exe | Where Name -NotMatch '.*NoDB\.exe$' | % {
New-Object psobject -Property #{
No = [int]([regex]::Match($_.Name, '(?<=CL)\d+').Value)
Name = $_.FullName
}
} | Sort No -Descending | Select -ExpandProperty Name -First 1 | Invoke-Item -s2 -sp"-SilentInstallation=standalone -UpdateMaterials=yestoall -UpgradeDBIfRequired=yes"
But I receive error:
Invoke-Item : A parameter cannot be found that matches parameter name 's2'.
At line:20 char:78
+ ... ding | Select -ExpandProperty Name -First 1 | Invoke-Item -s2 -sp"-Si ...
+ ~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Item], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.InvokeItemCommand

You get the error because you pass the parameters to the Invoke-Item cmdlet and not to your application,
Try to invoke your executeable with & and pass the parameters:
Get-ChildItem "D:\" -Filter *.exe | Where Name -NotMatch '.*NoDB\.exe$' | % {
New-Object psobject -Property #{
No = [int]([regex]::Match($_.Name, '(?<=CL)\d+').Value)
Name = $_.FullName
}
} | Sort No -Descending | Select -ExpandProperty Name -First 1 |
Foreach { & $_ -s2 -sp"-SilentInstallation=standalone -UpdateMaterials=yestoall -UpgradeDBIfRequired=yes"}

Related

Generate a report of entire D: Drive using PowerShell

I am new to PowerShell scripting. For one of my School project I need to generate a report of the entire D Drive. I need to list all the folders sorted according to the size
Summary of the work I have done so far:
I have installed a PowerShell module from this website
https://www.gngrninja.com/script-ninja/2016/5/24/powershell-calculating-folder-sizes
using Install-Module PSFolderSize
After installing if I run the command Get-FolderSize I'm getting the FolderSize for the path I'm running from. The foldersize is not running for all the folders in the directory.
I am facing difficulty traversing through all the folders.
Expected Output:
+-------------+--------------+--------------+-----------+-----------------------+-----------+
| FolderName | Size(Bytes) | Size(MB) | Size(GB) | FullPath | HostName |
+-------------+--------------+--------------+-----------+-----------------------+-----------+
| Disney | 454545448889 | 433488.32024 | 423.32844 | D:\Videos\Disney | localhost |
| Universal | 25454544884 | 24275.34569 | 23.70639 | D:\Videos\Universal | localhost |
| Fox Studios | 8803063287 | 8395.25536 | 8.19849 | D:\Videos\Fox Studios | localhost |
+-------------+--------------+--------------+-----------+-----------------------+-----------+
Can anyone help me where to start?
I would use other tools (like TreeSize) for creating reports like this because of the speed and long filename problematics.
However you could solve your task with the following powershell command without downloading an other Module.
For each subfolder inside your D:\ you have to receive your required data.
You have to calculate the size of each directory by looking for each file Get-ChildItem -Path $Folder.FullName -Recurse -Force and sum up the lenght of all files.
Here you can use the Measure-Object -Property Length -Sum. Depending on the directory size this task will take some time.
Take a look here if you struggle with long file name issues.
After collection and adding all data to an output variable use Select-Object -Property 'FolderName', 'Size(Bytes)', 'Size(MB)', 'Size(GB)', 'FullPath', 'HostName' for sorting the header order.
The command Sort-Object -Property 'Size(Bytes)', 'FolderName' will sort the output depending on the folder size and name.
For a nice looking output use Format-Table.
[System.String]$Path = 'D:\'
[PSCustomObject[]]$Output = #()
foreach ($Folder in (Get-ChildItem -Path $Path -Directory))
{
[System.Int64]$Size = (Get-ChildItem -Path $Folder.FullName -Recurse -Force | Measure-Object -Property Length -Sum).Sum
[System.Collections.Hashtable]$Hashtable = #{
'FolderName' = $Folder.Name
'Size(Bytes)' = $Size
'Size(MB)' = $Size / 1MB
'Size(GB)' = $Size / 1GB
'FullPath' = $Folder.FullName
'HostName' = $env:COMPUTERNAME
}
$Output += New-Object -TypeName 'PSCustomObject' -Property $Hashtable
}
$Output | `
Select-Object -Property 'FolderName', 'Size(Bytes)', 'Size(MB)', 'Size(GB)', 'FullPath', 'HostName' | `
Sort-Object -Property 'Size(Bytes)', 'FolderName' | `
Format-Table
[System.String]$Path = 'D:\'
[PSCustomObject[]]$Output = #()
foreach ($Folder in (Get-ChildItem -Recurse $Path | Where-Object { $_.PSIsContainer }))
{
[System.Int64]$Size = (Get-ChildItem -Path $Folder.FullName -Recurse -Force | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
[System.Collections.Hashtable]$Hashtable = #{
'FolderName' = $Folder.Name
'Size(Bytes)' = $Size
'Size(MB)' = [Math]::Round($Size / 1MB ,2)
'Size(GB)' = [Math]::Round($Size / 1GB,2)
'FullPath' = $Folder.FullName
'HostName' = $env:COMPUTERNAME
}
$Output += New-Object -TypeName 'PSCustomObject' -Property $Hashtable
}
$Output | `
Select-Object -Property 'FolderName', 'Size(Bytes)', 'Size(MB)', 'Size(GB)', 'FullPath', 'HostName' | `
Sort-Object -Property 'Size(Bytes)' , 'FolderName' -Descending | `
Format-Table

Powershell: how to replace a value within format-table

I want to shorten Directory with relative path:
$Dir = get-childitem C:\temp -recurse
$List = $Dir | where {$_.extension -eq ".txt"}
$List | format-table name, Directory -replace "C:\temp", ""
I get this error:
Format-Table : A parameter cannot be found that matches parameter name 'replace'.
At line:3 char:38
+ $List | format-table name, Directory -replace "C:\temp", ""
+ ~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Format-Table], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.FormatTableCommand
What's the right syntax ?
You can use a calculated property. Example:
$List | Format-Table name,
#{Name = "Directory"; $Expression = {$_.FullName -replace "C:\\temp", ""}}
A calculated property is simply a hashtable that dictates the content of the property. Calculated properties are available with formatting cmdlets that select properties and output a new custom object (e.g, Select-Object, Format-List, etc.).
(As an aside: The -replace operator uses a regular expression, so you would need to write C:\\temp instead of just C:\temp.)
If your goal is to output file system item directory names: Directory is not a property of all file system objects. Is this what you mean?
Get-ChildItem C:\Temp\*.txt -Recurse | Format-Table Name,
#{Name = "Directory"; Expression = {$_.FullName -replace 'C:\\temp', ''}}
Note how this command takes advantage of the pipeline (no need for the intermediate $List or $Dir variables).
To add to #Bill_Stewart's Answer.
$Dir = get-childitem C:\temp -recurse
$List = $Dir | where {$_.extension -eq ".txt"}
$List | format-table name, #{Label="Directory"; Expression={$_.Directory -replace "C:\\temp", ""}}

Compare two files in two different folders and perofrm installation of that file with PowerShell

I have a PowerShell script which compares two files in two different folders. If a file with the proper number exists in the first folder then it runs it.
If the file doesn't exist in the first folder then it copies it from the second folder to the first folder and runs it from the first folder.
function Invoke-InstallationOfANewBuild()
{
param (
$ptud = "$($env:USERPROFILE)\Desktop\",
$ptbf = "\\r\P\Al\O\D B\R 017\x64"
)
begin {
$output1 = Get-ChildItem $ptbf -Filter *.exe | Where Name -NotMatch '.*NoDB\.exe$' | % {
New-Object psobject -Property #{
No = [int]([regex]::Match($_.Name, '(?<=CL)\d+').Value)
Name = $_.FullName
}
} | Sort No -Descending | Select -ExpandProperty Name -First 1
$output2 = Get-ChildItem $ptbf -Filter *.exe | Where Name -NotMatch '.*NoDB\.exe$' | % {
New-Object psobject -Property #{
No = [int]([regex]::Match($_.Name, '(?<=CL)\d+').Value)
Name = $_.FullName
} | Sort No -Descending | Select -ExpandProperty Name -First 1
}
Compare-Object -ReferenceObject $output1 -DifferenceObject $output2
}
process {
if ($LASTEXITCODE = 0)
{
Get-ChildItem $ptud -Filter *.exe | Where Name -NotMatch '.*NoDB\.exe$' | % {
New-Object psobject -Property #{
No = [int]([regex]::Match($_.Name, '(?<=CL)\d+').Value)
Name = $_.FullName
}
} | Sort No -Descending | Select -ExpandProperty Name -First 1 | Foreach { & $_ -s2 -sp"-SilentInstallation=standalone -UpdateMaterials=yestoall -UpgradeDBIfRequired=yes" }
}
else
{
Get-ChildItem $ptbf -Filter *.exe | Where Name -NotMatch '.*NoDB\.exe$' | % {
New-Object psobject -Property #{
No = [int]([regex]::Match($_.Name, '(?<=CL)\d+').Value)
Name = $_.FullName
}
} | Sort No -Descending | Select -ExpandProperty Name -First 1 | Copy-Item -Destination $ptud | Foreach { & $_ -s2 -sp"-SilentInstallation=standalone -UpdateMaterials=yestoall -UpgradeDBIfRequired=yes" }
}
}
end { return $LASTEXITCODE }
}
I have a problem in the else block - file copies from the second folder to the first folder but the file execution is not started.
Also I am looking for better solution with if block. I want to say - if operation Compare-Object returns true than start everything in if block, if operation returns false (for example file with such doesn't exist in 1st folder) -than start everything in else block.
For your compare try this:
$compare = Compare-Object -ReferenceObject $A -DifferenceObject $B |
Where-Object { $_.SideIndicator -eq '=>' } |
Measure-Object -Property inputObject
$compare.count -gt 0 # for your if condition
for your copy-object problem, try this:
the Tee-Object wil duplicate the pipeline to a variable
Get-ChildItem $ptbf -Filter *.exe | Where Name -NotMatch '.*NoDB\.exe$' | % {
New-Object psobject -Property #{
No = [int]([regex]::Match($_.Name, '(?<=CL)\d+').Value)
Name = $_.FullName
}
} | Sort No -Descending | Select -ExpandProperty Name -First 1 | Tee-Object -variable Duplicate | Copy-Item -Destination $ptud
$duplicate | Foreach { & $_ -s2 -sp"-SilentInstallation=standalone -UpdateMaterials=yestoall -UpgradeDBIfRequired=yes" }

Powershell latest MSBuild path

After trying a number of approaches, including what seemed an excellent suggestion at http://www.bdevuyst.com/powershell-path-msbuild-exe/, which gave me an error, I tried to break it down. Though I get the latest MSBuild registry key (14.0), I still get this error when I try to extract the path to MSBuild:
Get-ItemProperty : Cannot find path 'C:\USERS\user\Desktop\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\MSBuild\ToolsVersions\14.0' because it does not exist.
At C:\USERS\mtroi\Desktop\VSS_POC1_Setup.ps1:529 char:5
+ Get-ItemProperty -Path $MsBuildVersion -Name MSBuildToolsPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\USERS\mtroi\...lsVersions\14.0:String) [Get-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand
# 32bit or 64bit local OS?
if($ENV:PROCESSOR_ARCHITECTURE -eq "x86")
{$HKLMpath = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\"}
elseif($ENV:PROCESSOR_ARCHITECTURE -eq "AMD64")
{$HKLMpath = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\MSBuild\ToolsVersions\"}
else
{Write-Host "Local processor architecture not supported. Exiting installation..."; EXIT}
# Which path (version) of local MSBuild?
$_decSep = [System.Threading.Thread]::CurrentThread.CurrentUICulture.NumberFormat.CurrencyDecimalSeparator;
$MsBuild1 = #(Get-ChildItem -Path $HKLMpath | Where { $_.Name -match '\\\d+.\d+$' })
ForEach ($build in $MsBuild1)
{
$Expression=$Expression+","+[System.Convert]::ToDecimal($build.Name.Substring($build.Name.LastIndexOf("\") + 1))
}
$MsBuildVersion = Get-ChildItem -Path $HKLMpath | Where { $_.Name -match '\\\d+.\d+$' } |
Sort-Object -Property #{Expression=$Expression} -Descending |
Select-Object -First 1 #| Get-ItemProperty -Name MSBuildToolsPath
Get-ItemProperty -Path $MsBuildVersion -Name MSBuildToolsPath

How to declare a snippet containing variables as a variable to avoid code duplication using PowerShell?

The snippet (Get-Content $_.FullName | Select-Object -First 1) is called three times. The aim is to declare it as a variable to avoid code duplication.
Get-ChildItem "$env:ChocolateyInstall\lib\eclipse.*" -Recurse -Filter "eclipseInstall.zip.txt" |
ForEach-Object{ if (((Get-Content $_.FullName | Select-Object -First 1) -match "eclipse") -and (Test-Path -Path (Get-Content $_.FullName | Select-Object -First 1))){Remove-Item -Recurse -Force (Get-Content $_.FullName | Select-Object -First 1)}}
Attempt
$a = (Get-Content $_.FullName | Select-Object -First 1)
Get-ChildItem "$env:ChocolateyInstall\lib\eclipse.*" -Recurse -Filter "eclipseInstall.zip.txt" |
ForEach-Object{ if (($a -match "eclipse") -and (Test-Path -Path (Get-Content $_.FullName | Select-Object -First 1))){Write-Host "hello"}}
Result
PS C:\Windows\system32> . "C:\temp\powershelltest\test.ps1"
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At C:\temp\powershelltest\test.ps1:1 char:19
+ $a = (Get-Content $_.FullName | Select-Object -First 1)
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentC
ommand
You can assign a snippet of code to a variable like this:
$a = { Get-Content $_.FullName | Select-Object -First 1 }
Then execute the snippet at any time with & $a (you would need to pipe an object to it). I'm not sure this is necessary in your example though.