Issue with QR Decoding using Zxing.Net in Powershell - Cannot find an overload for "Decode" and the argument count: "1" - powershell

I am trying to decode an QR Code in PowerShell with using Zxing.net (https://github.com/micjahn/ZXing.Net)
There is a HowTo at this page but I am not able to use it that way:
https://github.com/micjahn/ZXing.Net/wiki/Using-ZXing.Net-with-Powershell
Everytime I run the script I receive the following error message:
Cannot find an overload for "Decode" and the argument count: "1".
At C:\Users\ww\Desktop\reader.ps1:13 char:1
+ $result = $reader.Decode($bitmap)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
My whole script is:
Add-Type -Path "C:\Users\ww\Desktop\zxing.net\lib\net45\zxing.dll"
$reader = New-Object -TypeName ZXing.BarcodeReader
$reader.Options.TryHarder=1
# set TryHarder option to true, other options can be set the same way
$bitmap = [System.Drawing.Bitmap]::FromFile("C:\Users\ww\Desktop\abc.bmp")
$result = $reader.Decode($bitmap)
$bitmap.Dispose()
$result.Text
I only know "overload" from Java, where I can use different parameters for the same function, but in this case it makes no sense to me (I am not a very experienced programmer).
Is it possible that I am using the wrong .dll? I downloaded the Nuget-Package from https://www.nuget.org/packages/ZXing.Net/0.16.5, then extracted it via 7-Zip. I have tried various .dll (net40, netcoreapp3.0, portable, net20,...) but the result was always the same.
I also found this Github thread, where it seems rather easy to get everything working.
Could anyone give me a hint what is wrong with my implementation?
Thank you!

The script as-is should work fine. Make sure you are using the .dll for the appropriate version of .NET installed on your system. For example, I have .NET version 4.8, so I used the .dll for the highest version available, 4.7. My file-path is C:\...\ZXing.Net.0.16.5.0\net4.7\zxing.dll .
Add-Type -Path "C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Zxing\zxing.dll"
$reader = New-Object -TypeName ZXing.BarcodeReader
$reader.Options.TryHarder = 1 # set TryHarder option to true, other options can be set the same way
$bitmap = [System.Drawing.Bitmap]::FromFile("C:\Users\testUser\Pictures\QR.png")
$result = $reader.Decode($bitmap)
$bitmap.Dispose()
$result.Text
Console Output: https://www.youtube.com/watch?v=oHg5SJYRHA0

Related

InvalidCastException when trying to obtain UserPrincipal.Current

I have a PowerShell script which checks the currently signed in user as part of its start-up process. I'm using .Net to do this by adding the assembly:
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$cUser = [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
For almost everyone this works fine and I get a UserPrincipal object that I can use elsewhere, however there are a couple of users who get the following error when running it:
Unable to cast object of type 'System.DirectoryServices.AccountManagement.GroupPrincipal' to type 'System.DirectoryServices.AccountManagement.UserPrincipal'. At line:2 char:1
+ [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], InvalidCastException
+ FullyQualifiedErrorId : System.InvalidCastException
This is on a standard Windows 10 20H2 install and doesn't matter if PowerShell is running elevated or not. I've never seen this call return anything other than a UserPrincipal before, so I would be grateful for any advice: is this something I can deal with in code, or is there some underlying issue with the machines that are returning this exception?
I don't know if this is what you're looking for:
$cUser = Get-ADUser $Env:Username -Properties *
This has the most important attributes that you can use for whatever you want later on. It provides as much attribute as the code you posted that didn't work for some of the user.

How can I use the unmanaged UI Automation API from PowerShell

The UI Automation API for Windows is available from two DLLs.
One is a managed DLL, which is C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\UIAutomationClient.dll.
The other is an unmanaged DLL, which is C:\Windows\System32\UIAutomationCore.dll.
According to this post, the unmanaged API is superior to the managed API in terms of the number of visible elements, so I would like to use the unmanaged API.
I have tried three approaches, but all of them failed.
Would you tell me the correct approach?
Approach #1: New-Object -ComObject
$uia = New-Object -ComObject <ProgID of CUIAutomation>
$root = $uia.GetRootElement()
Failed because New-Object requires ProgID but CUIAutomation does not have ProgID.
Approach #2: Instantiation from CLSID
The CLSID of CUIAutomation is ff48dba4-60ef-4201-aa87-54103eef594e, then,
$type = [Type]::GetTypeFromCLSID("ff48dba4-60ef-4201-aa87-54103eef594e")
$uia = [Activator]::CreateInstance($type)
$root = $uia.GetRootElement()
but failed with the following error message.
I still do not know why.
Method invocation failed because [System.__ComObject] does not contain a method named 'GetRootElement'.
At line:1 char:1
+ $root = $uia.GetRootElement()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Approach #3: Add-Type
Add-Type -Path "C:\Windows\System32\UIAutomationCore.dll"
$uia = New-Object UIAutomationClient.CUIAutomation
$root = $uia.GetRootElement()
Failed because Add-Type expects managed DLLs.
Error message:
Add-Type : Could not load file or assembly 'file:///C:\Windows\System32\UIAutomationCore.dll' or one of its dependencies. The module was expected to contain an assembly manifest. At line:1 char:1
+ Add-Type -Path "C:\Windows\System32\UIAutomationCore.dll"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-Type], BadImageFormatException
+ FullyQualifiedErrorId : System.BadImageFormatException,Microsoft.PowerShell.Commands.AddTypeCommand
Edit (2018-06-12)
I tried another approach. (and failed)
Approach #4: Interop DLL
I do not really understand what exactly the Interop DLL is, but this post says the Interop DLL helped OP anyway.
I installed Visual Studio and generated Interop.UIAutomationClient.dll by following the procedures of the post.
Add-Type -Path "Interop.UIAutomationClient.dll"
$uia = New-Object UIAutomationClient.CUIAutomationClass
$root = $uia.GetRootElement()
$children = $root.FindAll([UIAutomationClient.TreeScope]::TreeScope_Children, $uia.CreateTrueCondition())
I succeeded in obtaining $root, but failed at the line of $children with the following error message.
Method invocation failed because [System.__ComObject] does not contain a method named 'FindAll'.
At line:1 char:1
+ $children = $root.FindAll([UIAutomationClient.TreeScope]::TreeScope_C ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
I still do not know why.
What about this?:
Add-Type -AssemblyName 'UIAutomationClient'
$ae = [System.Windows.Automation.AutomationElement]
$cTrue = [System.Windows.Automation.PropertyCondition]::TrueCondition
$root = $ae::RootElement
$winNames = $root.FindAll("Children", $cTrue).current.name
I have not yet resolved the problem, but finally found an alternative, that is C# Interactive.
I will leave this question for PowerShell users, but, if you can use C# Interactive as an alternative of PowerShell, the following section may help you.
Approach #5: C# Interactive
Install Visual Studio.
Generate Interop.UIAutomationClient.dll by following the procedures of this post.
Run the following script on csi.exe.
#r "Interop.UIAutomationClient.dll"
var uia = new UIAutomationClient.CUIAutomation();
var root = uia.GetRootElement();
var children = root.FindAll(UIAutomationClient.TreeScope.TreeScope_Children, uia.CreateTrueCondition());
FYI, C# Interactive works if only the following files exist in the same folder (i.e., you can use C# Interactive anywhere just by bringing the following files from the development environment).
C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe
C:\Program Files (x86)\MSBuild\14.0\Bin\csi.rsp
C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.CSharp.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.CSharp.Scripting.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.Scripting.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\System.AppContext.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\System.Collections.Immutable.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\System.Diagnostics.StackTrace.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\System.IO.FileSystem.dll
C:\Program Files (x86)\MSBuild\14.0\Bin\System.Reflection.Metadata.dll
Approach 2 you should get to the interface of
IID_IUIAutomation = "{30CBE57D-D9D0-452A-AB13-7AC5AC4825EE}"
CLSID_UIAutomationClient = "{944DE083-8FB8-45CF-BCB7-C477ACB2F897}"
;CoClasses
CLSID_CUIAutomation = "{FF48DBA4-60EF-4201-AA87-54103EEF594E}"
MS Doc states
Remarks
Every UI Automation client application must obtain this interface to a CUIAutomation object in order to gain access to the functionality of UI Automation.
The following example function creates a CUIAutomation object and obtains the
IUIAutomation interface.
IUIAutomation *g_pAutomation;
BOOL InitializeUIAutomation()
{
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IUIAutomation), (void**)&g_pAutomation);
return (SUCCEEDED(hr));
}
I was not able to get it working in PS but maybe this answers helps partly in the right direction (I have it working in AutoIt but that works differently, you can find it with AutoIt IUIAutomation on google)
$objCUI=[System.Runtime.InteropServices.Marshal]::GetTypeFromCLSID("30CBE57D-D9D0-452A-AB13-7AC5AC4825EE")
or
$Type = [Type]::GetTypeFromCLSID('30CBE57D-D9D0-452A-AB13-7AC5AC4825EE')
$objCUI = [System.Activator]::CreateInstance($Type)
both run but when I come to
$rootEl = $objCUI.GetType().InvokeMember(
"GetRootElement",
"InvokeMethod",
$Null,
$objCUI,
#()
)
I get errors

Why can't I instance a chromeoptions object with selenium in powershell?

I'm trying to use Powershell v5.1 on a Windows 10 machine to automate chrome tasks with Selenium chromedriver, and I'm having trouble creating a ChromeOptions object in PS after importing all the relevant dlls. Every source I've found says the correct object instantiation is done thus:
ChromeOptions options = new Chromeoptions();
But that results in this error:
At line:1 char:43
+ chromeoptions options = new chromeoptions();
+ ~
An expression was expected after '('.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ExpectedExpression
This is after I've imported these:
add-type -path "D:\\selenium\selenium.webdriverbackedselenium.dll"
add-type -path "D:\\selenium\thoughtworks.selenium.core.dll"
add-type -path "D:\\selenium\webdriver.support.dll"
add-type -path "D:\\selenium\webdriver.support.dll"
Am I missing any dlls required to instantiate chromeoptions objects? I can open chrome fine with chromedriver and navigate normally, but I need to configure some things before it opens or it's essentially useless to me. Thanks for any and all help!
I literally started playing with Selenium today because i want to try and scrape dynamic loaded data (javascript). Anyway
You are copying C# code and expecting it to work. You need to convert it to PS code (or run is as C# code in PS)
ChromeOptions options = new Chromeoptions();
becomes
$chromeOptions = New-Object OpenQA.Selenium.Chrome.ChromeOptions
$chromeOptions now has methods and properties that you can access, such as AddArgument for instance.
Once you created your ChromeOptions-object, you need to add it to the driver.
$driver = New-Object OpenQA.Selenium.Chrome.ChromeDriver($chromeOptions)

reference assembly in Powershell script

In Visual Studio I'm able to simply add a reference to an assembly, for example: Interop.ADODB.
How do I do this in powershell? The following is exploding
[Reflection.Assembly]::LoadWithPartialName("Interop.ADODB")
$conn = New-Object ADODB.Connection
And here is the error message
New-Object : Constructor not found. Cannot find an appropriate constructor for type ADODB.Connection.
At C:\Users\michaelr\Desktop\jet-project\PS\test.ps1:3 char:19
+ $conn = New-Object <<<< ADODB.Connection
+ CategoryInfo : ObjectNotFound: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : CannotFindAppropriateCtor,Microsoft.PowerShell.Commands.NewObjectCommand
I'm on Windows 7 x64.
Use this line instead:
$conn = New-Object -comobject ADODB.Connection
Powershell understand com object natively (well to the extent it's possible for objects that don't always have a lot of metadata) and does all the interop for you. You just need to tell powershell that it's a COM object. You don't need to reference the interop assemblies explicitly.
Having said that, depending on your task you might be better off using a native .net provider instead of ADODB.
You're looking for the Add-Type cmdlet, which lets you either compile .NET code into an in-memory assembly, or load an assembly from disk.
Check out the -AssemblyName parameter if you want to load an assembly from the GAC, or the -Path parameter if you know exactly where the DLL you want to load is.
The answer's right in front of you:
Cannot find an appropriate constructor for type ADODB.Connection
You need to pass the connection string to the constructor like this:
$c = new-object ADODB.connection "server=foo;user id=bar ..."
However, I don't understand why you want to use 1998-era ADODB in .NET when you can use System.Data instead. Check out this MSDN article on accessing databases with PowerShell:
http://technet.microsoft.com/en-us/magazine/hh855069.aspx

Windows RT Powershell (PermissionDenied) on New-Object

I am trying to instantiate an object in Powershell for Windows RT, but keep getting the following error.
PS > $foo = New-Object System.Security.Cryptography.SHA1Managed
New-Object : Cannot create type. Only core types are supported in this language mode.
At line:1 char:8
+ $foo = New-Object System.Security.Cryptography.SHA1Managed
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [New-Object], PSNotSupportedException
+ FullyQualifiedErrorId : CannotCreateTypeConstrainedLanguage,Microsoft.PowerShell.Commands.NewObjectCommand
I just spent the last thirty minutes engaged in some pretty heavy Google-fu and was unable to find anything even close to a similar problem, let alone an answer. My hope is that I just need to configure something; my fear is that Windows RT ships with a crippled version of Powershell.
Does anyone know which case it is?
Yup, Windows RT ships with a locked down version of PowerShell - it operates in ConstrainedLanguageMode which prevents most interaction (prop setters/method calls) with .NET. It also has a limited command set IIRC.