Creating Key in regedit with "/"in the name - powershell

Hi i'm just wondering im currently creating folder on my registry this is my code
function AddMachineRegistry{
param(
[string] $registryPath = $(throw "registryPath is a required parameter"),
[string] $name = $(throw "name is a required parameter"),
[int] $value = $(throw "value is a required parameter")
)
IF(!(Test-Path $registryPath))
{
New-Item -Path $registryPath -ItemType Key -Force | Out-Null
}
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -force | Out-Null
}
and tried to used it like this
AddMachineRegistry "HKLM:\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 40/128\" "Enabled" 0
basically im trying to create a key with the name of "RC4 40/128" but when i execute it it creates "RC4 40" folder and under that it creates "128"
im just wondering is it possible to create that? since im currently using "New-Item" and just giving it a path. i want my folder to named "RC4 40/128"

The easiest way will be invoking & REG ADD (basically, using CMD for the task) since PowerShell wants to interpret the forward slash as a delimiter. I just had a problem at work recently where I ran into this problem and could not find any solutions beyond that one.
A small tip: | Out-Null is a very slow operation and if you plan on calling anything with it to scale, I'd recommend using $Null = or [Void]( ... )

Normaly you must use:
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\" -Name "RC4 40/128" -PropertyType DWORD -Value 0
In this case it will we be:
AddMachineRegistry "HKLM:\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\" "RC4 40/128" 0
There is no need to backslashes the "/". Alternative: you can put path in ' ' instead " ". Commands in ' ' change special characters to normal chars.

Related

Powershell New-Item call prepending path information when creating a symbolic link [duplicate]

I've written a script to create a series of symbolic links. I want to set the target value to $shortpath where
$shortpath = "%userprofile%\dir1\dir2\dir3\filename.ext"
The value of the $shortpath variable is valid and I can open it from the run command. The string that PS is trying to write at the creation of the symlink is different than anticipated. I expect that it would write the value of the string, or at least insert the value of the Env Variable. rather it is adding to the string I pass to it.
New-Item -Path $currpath -ItemType SymbolicLink -Value ($targetpath) -Force
I would expect a target value to be: c:\Users\UserName\dir1\dir2\dir3\filename.ext or %userprofile%\dir1\dir2\dir3\filename.ext
Instead, I am getting: C:\windows\system32%UserProfile$\dir1\dir2\dir3\filename.ext
example of output written to logfile:
wholepath = C:\Users\UserName\dir1\dir2\dir3\longfilename1.ext
spath = C:\Users\UserName\dir1\dir2\dir3\longfi~1.ext
envpath = C:\Users\UserName\
midpart = dir1\dir2\dir3\
filename = longfi~1.ext
targetpath = %UserProfile%\dir1\dir2\dir3\longfi~1.ext
Could anyone shed some light as to why this may be happening? The same thing is happening if i user mklink. I've added the entire script below:
function Get-ShortPathName
{
Param([string] $path)
$MethodDefinition = #'
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetShortPathNameW", SetLastError = true)]
public static extern int GetShortPathName(string pathName, System.Text.StringBuilder shortName, int cbShortName);
'#
$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru
$shortPath = New-Object System.Text.StringBuilder(500)
$retVal = $Kernel32::GetShortPathName($path, $shortPath, $shortPath.Capacity)
return $shortPath.ToString()
}
$logfile="C:\SwSetup\SymLinkScript\log.txt"
<#paths to orignials and place to copy to#>
$src = $env:userprofile + "\Firestone Technical Resources, Inc\Firestone Technical Resources, Inc Team Site - Documents\Danielle"
$dest = "C:\SwSetup\asdfg\"
$src = $src.Replace("\","\\")
<# grab the root object, and its children, from the src#>
$i = Get-ChildItem -LiteralPath $src -Recurse
<# recurse through the root and process, for lack of a better term, each object#>
$i | ForEach-Object {
Process {
$apath = $_.FullName -Replace $src,""
$cpath = $dest + $apath
<# Create Directory if it does not exist#>
If(!(Test-Path (Split-Path -Parent $cpath))){
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $cpath)
}
<#
Create the SymLink if it does not exist
mklink syntax | PowerShell equivalent
mklink /D Link Target | new-item -path <path to location> -itemtype symboliclink -name <the name> -value <path to target>
#>
If(!$_.PSIsContainer){
If(!(Get-Item $cpath -ErrorAction SilentlyContinue)){
<#establish 8.3path#>
$wholepath = ([WildcardPattern]::Escape($_.FullName))
$shortPath = Get-ShortPathName($wholepath)
$envpath = $shortpath.substring(0,18)
$midpart = ((Split-path $shortpath -parent).trimstart($envpath)) +"\"
$filename = Split-Path $shortpath -leaf
$targetpath = "%UserProfile%\" + $midpart + $filename
<#write to log file#>
"wholepath = " + $wholepath >> $logfile
"spath = " + $Shortpath >>$logfile
"envpath = " + $envpath >> $logfile
"midpart = " +$midpart >>$logfile
"filename = " + $filename >> $logfile
"targetpath = " + $targetpath >> $logfile
"cpath = " + [string]$cpath >> $logfile
"----------" >>$logfile
" " >>$logfile
<#create symlink#>
New-Item -Path $cpath -ItemType SymbolicLink -Value ($targetpath) -Force
<#cmd /c mklink $cpath $targetpath#>
<#create shortcut
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut($targetpath.substring(0,$targetpath.Length-4) + '.lnk')
$Shortcut.TargetPath = $targetpath
$Shortcut.Save()#>
}
}
}
}
Shortcut files (.lnk) do support cmd.exe-style environment variable references (e.g. %USERPROFILE%) in their properties, but there's a caveat:
When a shortcut file is created or modified with WshShell COM object's .CreateShortcut() API:
Assigning property values, say, .TargetPath = '%USERPROFILE%\Desktop' works as expected - that is, the string is stored as-is and the reference to environment variable %USERPROFILE% is only expanded at runtime, i.e. when the shortcut file is opened.
However, querying such properties via this COM API also performs expansion, so that you won't be able to get raw definitions, and won't be able to distinguish between the .TargetPath property containing %USERPROFILE%\Desktop and, say, verbatim C:\Users\jdoe\Desktop
When in doubt about a given .lnk file's actual property values, inspect it via File Explorer.
Symbolic links (symlinks) do not.
The target of a symbolic link must be specified as a literal path, which in your case means using PowerShell's environment-variable syntax (e.g., $env:UserProfile) in order to resolve the variable reference to its value up front:
# This results in a *literal* path, because $env:UserProfile is
# instantly resolved; the result can be used with New-Item / mklink
$literalTargetPath = "$env:UserProfile\" + $midpart + $filename
Passing something like '%USERPROFILE%\Desktop' to the -Value / -Target parameter of New-Item -Type SymbolicLink therefore does not work (as intended), but the symptom depends on which PowerShell edition you're running:
Windows PowerShell, which you're using, tries to verify the existence of the target path up front, and therefore fails to create the symlink, because it interprets %USERPROFILE%\Desktop verbatim, as a relative path (relative to the current directory, which is why the latter's path is prepended), which doesn't exist.
PowerShell (Core) 7+ also interprets the path verbatim, but it allows creating symlinks with not-yet-existing targets, so the symlink creation itself succeeds. However, trying to use the resulting symlink then fails, because its target doesn't exist.
First you have set a variable called $shortpath:
$shortpath = "%userprofile%\dir1\dir2\dir3\filename.ext"
and then you say:
New-Item -Path $currpath -ItemType SymbolicLink -Value ($targetpath)
-Force
I would expect a target value to be:
c:\Users\UserName\dir1\dir2\dir3\filename.ext or
%userprofile%\dir1\dir2\dir3\filename.ext
The reason your expectation is not met is that your New-Item line doesn't refer to your $shortpath variable.

Set a value for a DWORD32 value in the registry only if it already exists | PowerShell

I want to set a value for DWORD32 value in the registry only if it already exists.
This is my code:
Set-ItemProperty -Path $mypath -Name $myname -Value 0
The problem with this code is in the Set-ItemProperty class; It creates the DWORD32 value even if it doesn't exist, and I want to change its value only if it exists.
Any solutions?
Check if Get-ItemPropertyValue returns any success output while ignoring any errors (in PSv4-, use Get-ItemProperty):
if ($null -ne (Get-ItemPropertyValue -ErrorAction Ignore -LiteralPath $mypath -Name $myname)) {
Set-ItemProperty -LiteralPath $mypath -Name $myname -Value 0
}
Note:
The above just tests whether the registry value exists - it doesn't check its data type. For the latter, you could use (the value returned by Microsoft.Win32.RegistryKey.GetValueKind() is of type Microsoft.Win32.RegistryValueKind):
(Get-Item -LiteralPath $path).GetValueKind($myName) -eq 'Dword'
Note that use of Test-Path is not an option in this case, because it can only test for provider items (which map to registry keys), not also their properties (which map to registry values).

Powershell - Find hive with Specific Name and then add key

I'm currently trying to code a something in powershell that will look for a registry hive with the name "c02ebc5353d9cd11975200aa004ae40e" and then add a Binary key in for each instance that has a hive with that name.
I currently have the below code that will add in the code for one example I have manually found.
$path = "HKCU:\SOFTWARE\Microsoft\Office\15.0\Outlook\Profiles\Name Of Outlook Profile\c02ebc5353d9cd11975200aa004ae40e"
New-ItemProperty -Path $path -Name 00030354 -PropertyType Binary -Value ([byte[]](0x00,0x00,0x00,0x00)) -Force
and I have this bit of code that will search through the HKCU:
$listhkcu = get-childItem "HKCU:\" -recurse
Any ideas on how I would add this binary key in for each instance of a hive with this name?
Any ideas or help is greatly appreciated.
Try something like...
[byte[]]$stuff = $(0x30, 0x02, 0x08, 0xAF)
$path = 'HKCU:\Environment'
New-ItemProperty -Path $path -Name 'thing' -Value $stuff -PropertyType Binary
You want to see the value you just created?
Get-ItemProperty -Path $path -Name 'thing'
Now in RegEdit...
Check your search after the create.

Append an array using powershell

I have an array with 3 elements(feature) in my code. Currently i have declared them as $feature = "System","Battery","Signal","Current";
But in future there can be more features. So I thought of giving an option in my code to add new feature(implemented as GUI) and using $feature.Add("$new_feature") command.
This works perfectly for that particular run of the script. But when i run the script again, this new added feature is not appearing. How can i solve this issue, so that when ever new feature is added, then it will remain in the script for ever?
Is this possible?
The simplest approach would be to store the array data in a file:
# read array from file
$feature = #(Get-Content 'features.txt')
# write array back to file
$feature | Set-Content 'features.txt'
You can use $PSScriptRoot to get the location of the script file (so you can store the data file in the same folder). Prior to PowerShell v3 use the following command to determine the folder containing the script:
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
Another option is to store the data in the registry (easier to locate the data, but a little more complex to handle):
$key = 'HKCU:\some\key'
$name = 'features'
# read array from registry
$feature = #(Get-ItemProperty -Path $key -Name $name -EA SilentlyContinue | Select-Object -Expand $name)
# create registry value if it didn't exist before
if (-not $?) {
New-ItemProperty -Path $key -Name $name -Type MultiString -Value #()
}
# write array back to registry
Set-ItemProperty -Path $key -Name $name -Value $feature

How to set a binary registry value (REG_BINARY) with PowerShell?

How to set a binary registry value (REG_BINARY) with PowerShell?
Background:
I need to change some properties of the ASP.NET State service using a PowerShell script. Unfortunately, the built-in PowerShell cmdlet Set-Service only lets you modify the service description, startup type, display name, and status. I need to modify the Subsequent failures property found on the Recovery tab (when viewing the service's properties). I found that this value was stored in the registry as a REG_BINARY value.
An export of the value looks like this:
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\aspnet_state]
"FailureActions"=hex:50,33,01,00,00,00,00,00,00,00,00,00,03,00,00,00,0e,00,00,\
00,01,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00
In Powershell there is a Set-ItemProperty cmdlet with which you can set registry value values. For a string or dword value, you can just pass a string or an int. I know which hex value in the array to change, but I can't figure out how to set a binary value.
The following line gives you an example how to create one
New-ItemProperty -Path . -Name Test -PropertyType Binary -Value ([byte[]](0x30,0x31,0xFF))
and how to change an existing one:
Set-ItemProperty -Path . -Name Test -Value ([byte[]](0x33,0x32,0xFF))
Is it just me who feels this misses the main part of this question?
How would you go about changing the original:
50,33,01,00,00,00,00,00,00,00,00,00,03,00,00,00,0e,00,00,\
00,01,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00
Into a format like:
([byte[]](0x33,0x32,0xFF))
EDIT: After trying to get this working it turns out you just prefix all of the pairs with '0x'. Not sure why that was not mentioned in the answer. So just change the above to:
0x50,0x33,0x01,0x00,0x00,0x00,0x00,0x00... etc.
Then wrap that in the following:
([byte[]](0x50,0x33,0x01,0x00,0x00,0x00,0x00,0x00... etc.))
This post has helped me out with similar problem. Thanks!
Bringing xBr0k3n and Howard's answers together:
#Change these three to match up to the extracted registry data and run as Admin
$YourInput = "50,33,01,00,00,00,00,00,00,00,00,00,03,00,00,00,0e,00,00,00,01,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00,01,00,00,00,00,00,00,00"
$RegPath = 'HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\aspnet_state'
$AttrName = "FailureActions"
$hexified = $YourInput.Split(',') | % { "0x$_"}
New-ItemProperty -Path $RegPath -Name $AttrName -PropertyType Binary -Value ([byte[]]$hexified)
Resurrecting this.
Here's how you can modify registry item binary values concisely in easy-to-follow powershell. In this example DefaultConnectionSettings is the registry item with a REG_BINARY value that we're trying to modify.
$path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
$objName = "DefaultConnectionSettings"
$getObj = Get-ItemProperty -path $path -name $objName
$getObj.DefaultConnectionSettings[8] = 1
$objValue = $getObj.DefaultConnectionSettings
Set-ItemProperty -path $path -name $objName -Value $objValue
When you use Get-ItemProperty for a registry item with a REG_BINARY value, it gives you a number of child objects in a collection.
By referencing the name of the item (in this case we do getObj.DefaultConnectionSettings) as a child object of getObj, we get an array of values, where each binary value (i.e 50,33,01,00,00,00,00,00,04) has its own position in the array.
Because it is an array we can reference, modify, and iterate through it easily by doing $getObj.DefaultConnectionSettings[8] = 1 or whatever number you want in place of 8. The 8 refers to the position of the value in the array. In the example of 50,33,01,00,00,00,00,00,04 the 9th position is 04. Remember that, like other things, arrays start counting at 0.
Setting it = 1 will change that 04 value in the binary to 01 while leaving the rest of the values unchanged in the array.
Finally, we set the change in place with Set-ItemProperty -path $path -name $objName -Value $objValue
Hope this helps others.
FYI, you can also set binary values with the PSRemoteRegistry PowerShell module (
http://psremoteregistry.codeplex.com/), on local or remote computers.
$Key = 'SOFTWARE\MyCompany'
Set-RegBinary -Hive LocalMachine -ComputerName Server1 -Key $Key -Value RegBinary -Data #([char[]]'PowerShell')
Let's start with an integer:
$int = 0xffffffff
Get the bytes:
$bytes = [bitconverter]::GetBytes($int)
Using set-itemproperty with the little knows '-type' parameter that can be used with registry paths:
Set-ItemProperty hkcu:\key1 bin1 $bytes -type binary
Get it back:
$bytes = Get-ItemProperty hkcu:\key1 bin1 | % bin1
Turn 4 bytes into an int:
$int = [bitconverter]::toint32($bytes, 0)
'0x{0:x}' -f $int
0xffffffff
I had problems with the other solutions, here's what I found to work:
Short Answer:
New-ItemProperty -path $path -name $name -value [byte]0x00,0x01,0x02 -PropertyType Binary
Complete Example:
$path = "HKCU:\Software\Hex-Rays\"
$name = "StrWinStringTypes"
$value = [byte]0x00,0x01,0x02
#if key path found, just add/modify the value/data pair
If (Test-Path($path))
{
New-ItemProperty -path $path -name $name -value $value -PropertyType Binary -Force | Out-Null
}
#if key path not found, create it first before adding value/data
Else
{
New-Item -path $path -force
New-ItemProperty -path $path -name $name -value $value -PropertyType Binary -Force | Out-Null
}