WJ871

How to extract dynamic value from string

13 posts in this topic

I'm new to AutoIT and in need of some help.

The script I'm working on opens a certificate and navigates to the Details as in the attached screenshot. I am able to copy all 6 lines in the attached screenshot, but the only thing I want is the value for SERIALNUMBER. Below is my script so far.

Help would be very much appreciated! E.g.: What function to use? Should I go via Notepad?

#include <File.au3>
Opt("MustDeclareVars", 1)
Opt("WinDetectHiddenText", 1)

Global $PathToFiles = "C:\Test\"
Global $FilesToRename = ""
Global $Clipboard = ""
Global $Serialnumber = ""

$FilesToRename = _FileListToArray($PathToFiles, "*", 1)

Local $File = ShellExecute($PathToFiles & $FilesToRename[1], "", @SW_HIDE)
;ShellExecuteWait($PathToFiles & $FilesToRename[1], "", $SHEX_PROPERTIES, @SW_HIDE)
sleep (5000)
send ( "^{TAB}" )
send ( "{TAB}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{TAB}" )
send ( "^c")
sleep (3000)
WinClose ("Certificate")
$Clipboard = ClipGet()
consolewrite ($Clipboard)
Run("notepad.exe")
WinWaitActive("Untitled - Notepad")
Send($Clipboard)
;$Serialnumber = FileReadLine()
;ConsoleWrite($Serialnumber)

 

Thanks

Certificate.png

Share this post


Link to post
Share on other sites



Hi

Is that an INI file? Can you post a simulated certificate?

If it is INI, use IniRead()

 

Alternatively, use a regex?

https://www.regex101.com/


Skysnake

Why is the snake in the sky?

Share this post


Link to post
Share on other sites

Thanks for your quick response. I've attached a self-signed certificate(rename to .der), unfortunately it does not contain a serial number but in this case we could take the value of "OU" for example.

Not familiar with regex, I will have a look!

cert_der

Share this post


Link to post
Share on other sites

It opens the .der file so that the popup in the screenshot in the first post appears. At this point the array 'FilesToRename' contains only 1 certificate, later I will build in a loop to go through all files in the folder in 'PathToFiles'.

Share this post


Link to post
Share on other sites

Hello. You can use _StringBetween.

 

If you don't want to use Windows Automation funtions. you can use CertUtil.exe to get certificate info and then use _StringBetween.

 

Saludos

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Instead of openning the files properties, you should use some function to search informations directy in the file :

 

#include <AutoItConstants.au3>
#include <Array.au3>

Local $sCertfile = @Scriptdir  & "\file.cer"

Local $iPid = Run('certutil -dump "' & $sCertfile & '"', @SystemDir, @SW_HIDE, $STDOUT_CHILD)
ProcessWait($iPid)

Local $sContent = StdoutRead($iPid)
Local $aInfos = StringRegExp($sContent, "(?ms)(^[A-Z][^:]+\h):(.*?)(?=(?1)|\Z)", 3)
If @error Then Exit MsgBox(16, "Error", "Unable to get any certificate informations from this file.")

Local $aInfos2D[UBound($aInfos) / 2][2], $iIndex
For $i = 0 To UBound($aInfos) - 1 Step 2
    $iIndex = $i / 2
    $aInfos2D[$iIndex][0] = $aInfos[$i]
    $aInfos2D[$iIndex][1] = $aInfos[$i + 1]
Next

_ArrayDisplay($aInfos2D)

@Danyfirex : i'm too late... :D

 

 

Edited by jguinch
1 person likes this

Share this post


Link to post
Share on other sites

Thanks a lot for the advice! I came up with this and it seems to work fine.  I wonder if you see any flaws and if there are reasons why i would be better off using StringBetween or CertUtil.exe?

#include <File.au3>
#include <Array.au3>
Opt("MustDeclareVars", 1)
Opt("WinDetectHiddenText", 1)

Global $PathToFiles = "C:\Test\"
Global $FilesToRename = ""
Global $Clipboard = ""
Global $Line = ""
Global $Location = ""

$FilesToRename = _FileListToArray($PathToFiles, "*", 1)

Local $File = ShellExecute($PathToFiles & $FilesToRename[1], "", @SW_HIDE)
sleep (3000)
send ( "^{TAB}" )
send ( "{TAB}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{DOWN}" )
send ( "{TAB}" )
send ( "^c")
sleep (1500)
WinClose ("Certificate")
$Clipboard = ClipGet()
;consolewrite ($Clipboard)
$Line = StringSplit($Clipboard, @LF)
;_ArrayDisplay($Line, "2D Array")
For $x = 0 to $Line[0]
   $Location = StringInStr($Line[$x], "SERIALNUMBER")
   ;ConsoleWrite($Location)
   ;ConsoleWrite($Line[$x])
   If $Location <> "0" Then
      ;ConsoleWrite($Line[$x])
      Local $Serialfull = StringSplit($Line[$x], "=")
      ;_ArrayDisplay($Serialfull, "2D Array")
      Local $Serial = StringTrimLeft($Serialfull[2], 1)
      ConsoleWrite($Serial)
   EndIf
Next

 

Share this post


Link to post
Share on other sites
18 minutes ago, WJ871 said:

Thanks a lot for the advice! I came up with this and it seems to work fine.  I wonder if you see any flaws and if there are reasons why i would be better off using StringBetween or CertUtil.exe?

#include <File.au3>
#include <Array.au3>
Opt("MustDeclareVars", 1)
Opt("WinDetectHiddenText", 1)

Global $PathToFiles = "C:\Test\"
Global $FilesToRename = ""
Global $Clipboard = ""
Global $Line = ""
Global $Location = ""

$FilesToRename = _FileListToArray($PathToFiles, "*", 1)

For $i = 1 To $FilesToRename[0]
   Local $File = ShellExecute($PathToFiles & $FilesToRename[$i], "", @SW_HIDE)
   sleep (3000)
   send ( "^{TAB}" )
   send ( "{TAB}" )
   send ( "{DOWN}" )
   send ( "{DOWN}" )
   send ( "{DOWN}" )
   send ( "{DOWN}" )
   send ( "{DOWN}" )
   send ( "{DOWN}" )
   send ( "{DOWN}" )
   send ( "{TAB}" )
   send ( "^c")
   sleep (1500)
   WinClose ("Certificate")
   $Clipboard = ClipGet()
   $Line = StringSplit($Clipboard, @LF)
   For $x = 0 to $Line[0]
      $Location = StringInStr($Line[$x], "SERIALNUMBER")
      If $Location <> "0" Then
         Local $Serialfull = StringSplit($Line[$x], "=")
         Local $Serial = StringTrimLeft($Serialfull[2], 1)
      EndIf
   Next
ConsoleWrite($Serial)
Next

 

 

Share this post


Link to post
Share on other sites

#10 ·  Posted

Thanks again for the help so far. I'm now stuck at the renaming of the files, not sure whether to start a new topic or keep my project in this topic.

I have the script below, when running it on the 2 certificates in the screenshot it returns the correct filename for one certificate, but for the other one there's an ENTER somewhere that places the extension(.der) on a new line. This makes the FileMove-statement fail for that certificate. Ideas on how to remove if required are very welcome!

#include <File.au3>
#include <Array.au3>
Opt("MustDeclareVars", 1)
Opt("WinDetectHiddenText", 1)

;Set variables
Global $PathToFiles = "C:\Test\"
Global $FilesToRename = ""

;List all files in PathToFiles in FilesToRename array
$FilesToRename = _FileListToArray($PathToFiles, "*", 1)

;Loop through FilesToRename array
For $i = 1 To $FilesToRename[0]

   ;Save last 4 characters of each file in Extension
    Local $Extension = StringRight($FilesToRename[$i], 4)

   ;Open file if Extension is .der
    If $Extension = ".der" Then
         Local $File = ShellExecute($PathToFiles & $FilesToRename[$i], "", @SW_HIDE)
         ;Wait time for popup to open
         sleep (3000)
         ;Keystroke simulations for selecting the Subjects-entry on the Details tab and copying the content
         send ( "^{TAB}" )
         send ( "{TAB}" )
         send ( "{DOWN}" )
         send ( "{DOWN}" )
         send ( "{DOWN}" )
         send ( "{DOWN}" )
         send ( "{DOWN}" )
         send ( "{DOWN}" )
         send ( "{DOWN}" )
         send ( "{TAB}" )
         send ( "^c")
         ;Wait time after copy
         sleep (1500)
         ;Close popup
         WinClose ("Certificate")
         ;Get content of clipboard and save in Clipboard
         Local $Clipboard = ClipGet()
         ;Split content of Clipboard on LF/ENTER and save in Line array
         Local $Line = StringSplit($Clipboard, @LF)

      ;Loop through Line array
      For $x = 1 to $Line[0]
         ;Check if each line contains string "SERIALNUMBER", this will return 0 if the string is not found on a line and 1 if the "S" is on the first position of a line (or 2 if it's on the second position, etc.)
         Local $Location = StringInStr($Line[$x], "SERIALNUMBER")

         ;Check for position in Location where value is not "0"
         If $Location > 0 Then
            ;Split that line by = and save in Serialfull
            Local $Serialfull = StringSplit($Line[$x], "=")
            ;Trim 1 character of the left side of Serialfull (because it's a space) and save in Serial
            Local $Serial = "SHA" & StringTrimLeft($Serialfull[2], 1)
         EndIf
      ;End loop through Line array
      Next
   sleep(1000)
   ;Set the Serial as Filename
   FileMove($PathToFiles & $FilesToRename[$i], $PathToFiles & $Serial & $Extension)
   sleep(1000)
   ;ConsoleWrite($PathToFiles & $FilesToRename[$i] & @CRLF)
   ConsoleWrite($PathToFiles & $Serial & $Extension & @CRLF)
   ;Write each Serial in Console
   ;ConsoleWrite($Serial)
   EndIf
;End loop through FilesToRename array
Next

 

renametoserialerror.png

Share this post


Link to post
Share on other sites

#11 ·  Posted

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

17 hours ago, WJ871 said:

I wonder if you see any flaws and if there are reasons why i would be better off using StringBetween or CertUtil.exe?

Certutil is a command line tool which will help you to get the informations you want from a certificate file. _Stringbetween is an AutoIt function which can extract some text from a string.
The automation you did by accessing the file properties is the last way you should use because the automation of a Window can conflict with the user actions (mouse, keyboard of other windows) and the window you want to automate can differ between several computers (tabs are not the same, not the same options, or else...). The best way is to avoid the use of this kind of automation when possible. Sure, it's more complicated and often requires to have sufficient knowledges in scripting but if your code is good enough, you won't have any surprise. To help you, it's also possible to use some external command line tools to simplify the job.

For this reasons, danyfirex gave you an idea with certutil.exe (run it from your AutoIt script to get the certificate informations) and _Stringbetween to parse the result.

What I'm telling you is my own advice, but sure it can all be discussed. If your method suits you and it covers your needs, so much the better.

 

 

Edited by jguinch
1 person likes this

Share this post


Link to post
Share on other sites

#13 ·  Posted

2 hours ago, Danyfirex said:

Hello. You can do this.

 

ConsoleWrite($PathToFiles & StringRegExpReplace($Serial & $Extension, "\R+", "") & @CRLF)

Saludos

Works! Thanks!

jguinch: Also thanks for explaining. I have no doubt that there's better ways then I'm using, unfortunately I'm on a bit of a tight schedule so for now I'll stick to my solution (also because that one I understand :-) ). Meanwhile I'll keep practicing and dive into regex!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now