Reading Registry Keys to Check 32/64-bit Application - special-characters

I want to read out my application name via NSIS from the windows registry. The application name may be "Application (x86)" or "Application (x64)"
I'm using following code:
ReadRegStr $R1 HKLM "SOFTWARE\Something\Something\" "ApplicationName"
The output of the value of $R1 is always "Application" without the brackets.Does ReadRegStr always ignore special characters?Is there some workaround?

ReadRegStr does not filter the string in any way:
Section
; Write the test string first
WriteRegStr HKCU "Software\NSIS\Test\" "Application" "Application (x86)"
; ...and then read it and display the result
ReadRegStr $R1 HKCU "Software\NSIS\Test\" "Application"
MessageBox MB_OK "$R1"
; Cleanup
DeleteRegKey HKCU "Software\NSIS\Test\"
SectionEnd
Is it possible that you are reading an old string in the wrong place in the registry caused by registry redirection/reflection or 32 vs 64-bit views?
Monitor the installer with Process Monitor so you can see the actual place in the registry you are reading from and the value returned to the application.

Related

How to detect if a special file is running or not with powershell?

Get-Process only gives the result if a notepad or exe file is running but I want to know if a specific file (index.txt) which is in some folder is running or not in powershell
You can use the mainWindowTitle method and then select the names of the processes running. Something like this -
get-Process notepad | where-Object {$_.mainWindowTitle} | Select-Object id, name, mainwindowtitle
This will give you the list of notepads processes running, and if you find your file index.txt under the MainWindowTitle header then, you can confirm that your file is running indeed.
Get-Process gets all running processes.
A text file is not a process, it of course is an object opened by / in a process (whether PS started it or not), notepad, winword, etc...
PS can be used to start a process, say notepad, but PS does not own it, the exe does.
So, a file, in the context you are asking, is never running in PS, the process (running on your system) can be looked up using Get-Process (or the old Tasklist tool which Get-Process replaces) as well as the path information of the running process.
Start notepad manually and open a text file.
Run Get-Process and ask for all values of the notepad process.
You will see the Get-Process brings back a whole lot of info for you to select from.
Note that it is the MainWindowTitle, which shows what file the Notepad process has open, but no where in this results does it say where that file (path) is ran from.
Get-Process Notepad | Select-Object *
Name : notepad
Id : 20516
...
Path : C:\WINDOWS\system32\notepad.exe
Company : Microsoft Corporation
CPU : 2.515625
ProductVersion : 10.0.17134.1
Description : Notepad
Product : Microsoft® Windows® Operating System
__NounName : Process
...
MainWindowTitle : news-stuff.txt - Notepad
MainModule : System.Diagnostics.ProcessModule (notepad.exe)
...
Note:
This answer tells you if a given file is currently held open by someone.
If you also need to know who (what process) has it open, see the answers to this related question, but note that they require either installation of a utility (handle.exe) or prior configuration of the system with administrative privileges (openfiles)
If you want a conveniently packaged form of the technique presented in this answer, you can download function Get-OpenFiles from this Gist, which supports finding all open files in a given directory [subtree].
Files, unlike processes, aren't running, so I assume that you meant to test if a file is currently open (has been opened, possibly by another process, for reading and/or writing, and hasn't been closed yet).
The following snippet detects if file someFile.txt in the current dir. is currently open elsewhere:
$isOpen = try {
[IO.File]::Open("$PWD/someFile.txt", 'Open', 'Read', 'None').Close()
$false # file NOT open elsewhere
}
catch {
# See if the exception is a sharing / locking error, which indicates that the file is open.
if (
$_.Exception.InnerException -is [System.IO.IOException] -and
($_.Exception.InnerException.HResult -band 0x21) -in 0x21, 0x20
) {
$true # file IS open elsewhere
}
else {
Throw # unexpected error, relay the exception
}
}
$isOpen # echo the result
Note the $PWD/ before someFile.txt, which explicitly prepends the path to the current directory so as to pass a full filename. This is necessary, because the .NET framework typically has a different current directory. Prepending $PWD/ doesn't work in all situations, however; you can read more about it and find a fully robust solution here.
The code tries to open the file for reading with an exclusive lock (a sharing mode of None), which fails if the file is currently open.
Note, however, that this only works if you have permission to at least read the file.
If you don't, the test cannot be performed, and the code relays the [System.UnauthorizedAccessException] that occurred; similarly, exceptions from other unexpected conditions are relayed, such as the specified file not existing ([System.IO.FileNotFoundException]).
[System.IO.IOException] can indicate a range of error conditions (and operator -is also matches derived classes such as [System.IO.FileNotFoundException]), so in order to specifically detect sharing/locking errors, the code must test the .HResult property of the exception for containing Win32 API error codes ERROR_SHARING_VIOLATION (0x20) or ERROR_LOCK_VIOLATION (0x21).
Taking a step back: If the intent is ultimately to process the file [content] yourself, it's better not to perform a separate test beforehand, because the file may get opened again between performing your test and your subsequent attempt to open it; instead, simply try to open the file yourself and handle any failure - see this (C#-based) answer.

NSIS read registry key returns empty for postgresql

using the NSIS example for read registry keys, I tried to read postgres registry keys but always returns empty, I verified that the path is correct but NSIS ReadRegStr shows empty with quotes, without quotes. ( The original example reads from Software\Microsoft\Windows\CurrentVersion and it recovers the key,value correctly)
loop1:
ClearErrors
EnumRegValue $1 HKLM "SOFTWARE\PostgreSQL\Installations\postgresql-x64-10" $0
IfErrors done
IntOp $0 $0 + 1
ReadRegStr $2 HKLM SOFTWARE\PostgreSQL\Installations\postgresql-x64-10 $1
MessageBox MB_YESNO|MB_ICONQUESTION "$1 = $2$\n$\nMore?" IDYES loop1
done:
any suggestion?
thanks
64-bit versions of Windows has two registry views.
The registry redirector isolates 32-bit and 64-bit applications by providing separate logical views of certain portions of the registry on WOW64. The registry redirector intercepts 32-bit and 64-bit registry calls to their respective logical registry views and maps them to the corresponding physical registry location. The redirection process is transparent to the application. Therefore, a 32-bit application can access registry data as if it were running on 32-bit Windows even if the data is stored in a different location on 64-bit Windows.
Use SetRegView to read from the 64-bit view in NSIS:
Section
SetRegView 64
ReadRegStr ...
SetRegView lastused
SectionEnd

Test-Path powershell is returning True when it should be false

I am writing a module to run logparser queries. I wrote a function that checks if LogParser is in the system root so that I can run logparser as a command in subsequent functions.
My code:
function Add-LogParser
{
if(Test-Path "C:\Windows\System32\LogParser.exe")
{
Write-Host -ForegroundColor Cyan "Log Parser is in System Root"
}
else
{
Copy-Item "C:\Program Files (x86)\WindowsPowerShell\Modules\Dealogic.LogAnalysis\LogParser.exe" -Destination "C:\Windows\System32\" -Force
if(Test-Path "C:\Windows\System32\LogParser.exe")
{
Write-Host -ForegroundColor Cyan "Log Parser has been added to System Root"
}
else
{
Write-Host -ForegroundColor Red "Unable to add Log Parser to System Root. This is a requirement of the Dealogic Log Analysis Module. Please verify you have write to copy to the C:\Windows\System32\ folder."
break
}
}
}
I ran the function and the first time it added it to root fine. I ran the function again because it has logic to check that it is in the root and that worked fine. Then I deleted LogParser expecting the third time it will see it is on there and add it back to root, but instead, it thinks LogParser is still there. And even if I start new Powershell sessions and just tab over to the path it thinks its there.
Even outside of my code this command is not working properly:
Test-Path -LiteralPath C:\Windows\System32\LogParser.exe
Is this because it is in the system root? Is that cached in the Powershell profile or something? Since adding it to root is a one time thing I don't know that it affects my script, but I was surprised to see this behavior.
This seems to be a common pitfall when developing in a situation where the developer can accidentally or unwittingly switch between 32 bit and 64 bit Powershell environments.
I conducted the following tests:
Test: Create file in system32 only and check system32 and syswow64 from both 32 and 64 bit PowerShell.
Result: 32 bit session returned FALSE for both. 64 bit session returned TRUE for system32 and FALSE for syswow64.
Test: Create the file in syswow64 only and check both paths from both sessions.
Result: 32 bit session returned TRUE for both. 64 bit session returned FALSE for system32 and TRUE for syswow64.
Test: Create file in both locations and check both paths from both sessions.
Result: Both sessions returned TRUE for both paths.
Test: Create file in both locations and delete from system32 only.
Result: 32 bit session returns TRUE for both. 64 bit session returns true for syswow64 only.
Test: Create file in both locations and delete from syswow64 only.
Result: 32 bit session returned FALSE for both. 64 bit session returned TRUE for system32 only.
From this testing it appears that the 64 bit version is capable of accurately checking for files in both system32 and syswow64. The 32 bit application appears to be defaulting to using wow64. If the file is there it will return true regardless of what is in system32, and if the file is not there it will return false regardless of what is in system32.
Thanks to #Mathias R. Jessen for asking if the file exists in the syswow64 directory, as that reminded me that I've seen this before.
It looks like this all relates to redirection and reflection of keys under wow64. For more info search msdn Microsoft documentation for "Registry Keys affected by WOW64". This article https://support.microsoft.com/en-us/help/305097/how-to-view-the-system-registry-by-using-64-bit-versions-of-windows
contains some related info and includes this interesting line: "To support the co-existence of 32-bit and 64-bit COM registration and program states, WOW64 presents 32-bit programs with an alternate view of the registry."

Invoke FCIV within Powershell Script

I am using the FCIV ( Microsoft File Checksum Integrity Verifier ) executable to automatically calculate checksums for certain files.
I want to invoke this executable within a powershell script. This is my snippet within Powershell.
& "Path to FCIV.exe" –add "Base Dir" -bp "Base Dir" -r –xml "Path to XML"
This commands basically recurses and calculates checksums for all files under "Base Dir" and then outputs into an XML file. I am able to execute this command on Powershell prompt. But when I add this line into a script and execute the script, I get this error.
–add\*
Error msg : The system cannot find the path specified.
Error code : 3
I have tried everything from adding FCIV to PATH environment variable as well as providing the whole path to files.
Any suggestions on how to overcome this?

Windows Batch error: "'ping' is not recognized as an internal or external command operable program or batch file."

I am trying to run this command in windows:
ping -n 5 127.0.0.1 > nul
I get the error:
'ping' is not recognized as an internal or external command operable
program or batch fie.
Why can't windows find ping? Here is my script where it does not work:
#ECHO OFF
::set path
SET path=M:\\5.bmp
:findfile
IF EXIST %path% (
ECHO File found
) ELSE (
ECHO File not found
ping -n 5 127.0.0.1 > nul
goto findfile
)
You have overridden the PATH environment variable, so the command processor can no longer find the ping executable.
The fix is nice and simple - just use a different variable name!
:: set path
SET MyPath=M:\\5.bmp
:findfile
IF EXIST %MyPath% (
Please note that if you genuinely wanted to set the path environment variable, you should append to it like so:
REM Set temporarily for this session
SET PATH=%PATH%;C:\Some\Folder
REM Set permanently (but note - this change will not be made to this session)
SETX PATH=%PATH%;C:\Some\Folder
Hi to fix "ping" please follow below steps
Go to Properties in My computer
Advanced system settings ----->Advanced -----> Environment Variables
Select 'PATH' from the list of system variables and edit and set PATH to c:\windows\system32 ; this will solve your problem.
-----> if still u have a problem, do the below steps...
Control Panel --> System and security --> Windows Firewall --> Advanced settings --> Inbound rules --> New rule --> custom rule
in Protocol and ports: Protocol: ICMPv4
on the same panel go to customize, choose "Specific ICMP types", check the box "echo request"
The rest is trivial; go to next... next... and save it.
You should be done. This box responds ping from this point on.
Cheers
Prasad
How to diagnose this error:
'ping' is not recognized as an internal or external command operable
program or batch fie.
Because your path environment variable does not contain the directory that points to the executable: ping.exe. So the question becomes why can't your command line program cmd.exe locate ping.exe?
You can print out your path variable on the commandline like this:
echo %PATH%
Which prints for me:
C:\WINDOWS;C:\WINDOWS\system32;C:\Program Files\jZip;C:\MinGW\bin
The above string is delimited by semicolons(;). Notice the element called: C:\WINDOWS\System32, that is the element that defines where ping.exe can be located.
Solutions
You didn't specify C:\WINDOWS\System32 in your path variable. Make sure it is there.
ping.exe is missing. Find out who deleted it and put it back.
ping.exe is corrupt. Run it where it sits: C:\WINDOWS\System32\ping.exe, or replace ping.exe.
You have overridden the PATH variable before you look for it.