Copy files from COM device using AHK - autohotkey

I have a function which can effevtively copy a file from my android device,
GetDeviceFolder(deviceName) {
shell := ComObjCreate("Shell.Application")
computer := shell.Namespace("::{20d04fe0-3aea-1069-a2d8-08002b30309d}")
for item in computer.Items
if item.Name = deviceName
return item.GetFolder()
}
save_data_file()
{
GuiControlGet,phonename
GuiControlGet,datapath
GuiControlGet,savepath
phone := GetDeviceFolder(phonename)
phone.ParseName(datapath).InvokeVerb("copy")
}
however, I can't figure out how "paste" it to a local drive. I know it's in the clipboard because I can paste it manually after running this function.

The local disk also needs to be handled by COM.
Example:
GetDeviceFolder(deviceName) {
shell := ComObjCreate("Shell.Application")
computer := shell.Namespace("::{20d04fe0-3aea-1069-a2d8-08002b30309d}")
for item in computer.Items
if item.Name = deviceName
return item.GetFolder()
}
save_data_file(src, dest) {
src := StrSplit(src, "\", , 2)
dest := StrSplit(dest, "\", , 2)
GetDeviceFolder(src[1]).ParseName(src[2]).InvokeVerb("copy")
GetDeviceFolder(dest[1]).ParseName(dest[2]).InvokeVerb("paste")
}
save_data_file("Phone Name\Internal Storage\Download\5a5f641e9893c.jpg", "Disk Name (E:)\incoming")

I did it like using this helper function
InvokeVerb(path, menu, validate=True) {
;by A_Samurai
;v 1.0.1 http://sites.google.com/site/ahkref/custom-functions/invokeverb
objShell := ComObjCreate("Shell.Application")
if InStr(FileExist(path), "D") || InStr(path, "::{") {
;~ MsgBox % path
objFolder := objShell.NameSpace(path)
;~ MsgBox % namespace(path) . "k"
objFolderItem := objFolder.Self
}
else {
SplitPath, path, name, dir
;~ MsgBox % path . "`n" name . "`n" . dir
;~ loop, % path0
;~ MsgBox % path%A_index%
objFolder := objShell.NameSpace(dir)
objFolderItem := objFolder.ParseName(name)
}
if validate {
colVerbs := objFolderItem.Verbs
colVerbs.Count
loop % colVerbs.Count {
verb := colVerbs.Item(A_Index - 1)
retMenu := verb.name
StringReplace, retMenu, retMenu, &
if (retMenu = menu) {
verb.DoIt
Return True
}
}
Return False
} else
objFolderItem.InvokeVerbEx(Menu)
}
then I just did this:
InvokeVerb(savepath, "Paste", "false")

Related

Is there such function like IsCallable?

I'd like to have in AutoHotkey function named, for example IsCallable, that can tell me whether an object (or anything that can be stored in AHK variable) is callable.
A callable object includes:
a normal function represented as a string.
a function object by Func("somefuncname").
a BoundFunc Object.
The key point is, if fnobj is callable, then the user can write %fnobj%(...) to actually call something.
Clarify my idea with code below:
test_check_callable()
{
fnstr := "fnhello"
fnobjA := Func("fnhello")
fnobjB := fnobjA.bind("0th")
fnobjC := fnobjB
%fnstr%()
%fnobjA%("A1")
%fnobjB%("B1")
fnobjC.("C1", "C2")
r1 := IsCallable(fnstr) ; true
r2 := IsCallable(fnobjA) ; true
r3 := IsCallable(fnobjB) ; true
r4 := IsCallable(fnobjC) ; true
e1 := IsCallable("NoSuch") ; false
e2 := IsCallable({key1:"value1"}) ; false
}
fnhello(args*)
{
Dbgwin_Output("fnhello() parameters: " args.Length())
for i,arg in args
{
Dbgwin_Output(Format(" param{} = {}", i, arg))
}
}
IsCallable(pobj)
{
; How to implement this? IsFunc? IsObject?
}
I hope r1, r2, r3, r4 should all get true, and e1, e2 get false.
I'm using Autohotkey 1.1.36.2 .
PS: Dbgwin_Output() is implemented here: https://github.com/chjfth/AmHotkey/blob/master/libs/debugwin.ahk
If you used AHKv2, you could make use of HasMethod. I'd recommend the usage of AHKv2, it's already at the RC3 stage.
Something like this should work pretty well to cover all basic use cases:
fnStr := "fnHello"
fnObjA := %fnStr%
fnObjB := fnobjA.bind("0th")
fnObjC := fnObjB
class HelloClass
{
Call() => MsgBox("Hello")
}
fnClass := HelloClass()
class NotCallable
{
}
no1 := "NoSuch"
no2 := {key: "value"}
classNo := NotCallable()
MsgBox(
"`"fnHello`": " IsCallable("fnHello") "`n" ;support pure strings
"fnStr: " IsCallable(fnStr) "`n" ;support string objects
"fnObjA: " IsCallable(fnObjA) "`n" ;support user-defined function objects
"fnObjB: " IsCallable(fnObjB) "`n" ;support bound function objects
"fnObjC: " IsCallable(fnObjC) "`n" ;same as fnObjA
"`"MsgBox`": " IsCallable("MsgBox") "`n" ;support built-in functions as pure strings
"MsgBox: " IsCallable(MsgBox) "`n" ;support built-in functions
"fnClass: " IsCallable(fnClass) "`n`n" ;support user defined classes
"`"NoSuch`": " IsCallable("NoSuch") "`n"
"no1: " IsCallable(no1) "`n"
"no2: " IsCallable(no2) "`n"
"classNo: " IsCallable(classNo) "`n"
)
fnHello(param := "")
{
MsgBox("hi " param)
}
IsCallable(inp)
{
if (HasMethod(inp))
return true
try
{
inp := %inp%
}
catch
{
return false
}
return HasMethod(inp)
}
Result:
"fnHello": 1
fnStr: 1
fnObjA: 1
fnObjB: 1
fnObjC: 1
"MsgBox": 1
MsgBox: 1
fnClass: 1
"NoSuch": 0
no1: 0
no2: 0
classNo: 0

RegWrite not writing to the registry

ValueType := A_Args[1]
KeyName := A_Args[2]
ValueName := A_Args[3]
ValueData := A_Args[4]
Loop, %0%
params .= A_Space %A_Index%
; https://autohotkey.com/docs/Run#RunAs
full_command_line := DllCall("GetCommandLine", "str")
if !(A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)")) {
try {
if A_IsCompiled
Run *RunAs "%A_ScriptFullPath%" "%params%" /restart
else
Run *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%" "%params%"
}
ExitApp
}
RegWrite, % ValueType, % KeyName, % ValueName, % ValueData
Why is RegWrite not writing to the registry when I pass parameters to the script?
A_LastError codes
Code 87 means an invalid parameter. What are you passing to RegWrite?
Here's one function I use for debugging. If isCondition is true it shows a custom error message and stops everything.
fAbort(isCondition, sFuncName, sNote, dVars:="") {
If isCondition {
sAbortMessage := % sFuncName ": " sNote
. "`n`nA_LineNumber: """ A_LineNumber """`nErrorLevel: """ ErrorLevel """`nA_LastError: """ A_LastError """`n"
For sName, sValue in dVars
sAbortMessage .= "`n" sName ": """ sValue """"
MsgBox, 16,, % sAbortMessage
ExitApp
}
}
After a RegWrite it could be used like this:
fAbort(ErrorLevel ; 1, if RegWrite unsuccessful.
, "Script or function name here" ; Could use A_ThisFunc for current function name.
, "Registry write unsuccessful." ; Your custom message here.
, { x: "blabla", y: 13 } ; Additional vars you want to see in the msgbox.
)

Execute powershell command in running container via Docker API

I want to execute a powershell command in a docker container running on a windows host.
The specific command I want to execute is "powershell Get-PSDrive C | Select-Object Used,Free"
I have implemented this using the Docker API for python and it is simple like calling:
cmd = "powershell Get-PSDrive C | Select-Object Used,Free"
output = container.exec_run(cmd)
This works as intended, but I need to implement this in golang.
But somehow, it is not clear for me how to interact with the Docker API for golang. I looked into the API and was confused by the hijackedSession. How do I have to setup the calls for ContainerExecCreate, ContainerExecAttach and ContainerExecStart ?
I expect the golang script to deliver the same results like the python code does:
Used Free
---- ----
199181606912 307151622144
Which then can be parsed by me.
The HijackedResponse struct:
type HijackedResponse struct {
Conn net.Conn
Reader *bufio.Reader
}
You need to copy the response from the resp.Reader,here is my code:
package main
import (
"bytes"
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
"strings"
)
func readFromCommand() (string, error) {
cli, err := client.NewEnvClient()
if err != nil {
return "", err
}
ctx := context.Background()
config := types.ExecConfig{
Cmd: strings.Split("powershell Get-PSDrive C | Select-Object Used,Free", " "),
AttachStdout: true,
AttachStderr: true,
}
response, err := cli.ContainerExecCreate(ctx,
// container id
"cf59d65ab1", config)
if err != nil {
return "", err
}
execID := response.ID
resp, err := cli.ContainerExecAttach(ctx, execID, config)
if err != nil {
return "", err
}
defer resp.Close()
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
_, err = stdcopy.StdCopy(stdout, stderr, resp.Reader)
if err != nil {
return "", err
}
s := stdout.String()
fmt.Println(s)
i := stderr.String()
fmt.Println(i)
return s, nil
}
Do remember to change the container id.

Can powershell extract a .tgz file?

I'm brand new to powershell, and I'm trying to write a script to extract a .tar.gz file.
It requires 2 steps to unzip the file.
# Create a .tar file
7z.exe a -ttar files.tar *.txt
7z.exe a -tgzip files.tar.gz files.tar
# These 2 work
& 'C:\Program Files\7-Zip\7z.exe' e .\files.tar.gz
& 'C:\Program Files\7-Zip\7z.exe' x -aoa -ttar .\files.tar -o'c:\foobar'
I'm trying to combine these two commands into one command so that I can skip writing the files.tar file to disk.
However, when I try and combine the functions, I get the error message 'incorrect function'
Is there a way to combine these 2 7zip commands into 1?
& 'C:\Program Files\7-Zip\7z.exe' e .\files.tar.gz -so | & 'C:\Program Files\7-Zip\7z.exe' x -aoa -ttar -si -o'c:\foobar'
As you can see 7-Zip is not very good at this. People have been asking for
tarball atomic operation since 2009. Here is a small program
(490 KB) in Go that can do it, I compiled it for you.
package main
import (
"archive/tar"
"compress/gzip"
"flag"
"fmt"
"io"
"os"
"strings"
)
func main() {
flag.Parse() // get the arguments from command line
sourcefile := flag.Arg(0)
if sourcefile == "" {
fmt.Println("Usage : go-untar sourcefile.tar.gz")
os.Exit(1)
}
file, err := os.Open(sourcefile)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer file.Close()
var fileReader io.ReadCloser = file
// just in case we are reading a tar.gz file,
// add a filter to handle gzipped file
if strings.HasSuffix(sourcefile, ".gz") {
if fileReader, err = gzip.NewReader(file); err != nil {
fmt.Println(err)
os.Exit(1)
}
defer fileReader.Close()
}
tarBallReader := tar.NewReader(fileReader)
// Extracting tarred files
for {
header, err := tarBallReader.Next()
if err != nil {
if err == io.EOF {
break
}
fmt.Println(err)
os.Exit(1)
}
// get the individual filename and extract to the current directory
filename := header.Name
switch header.Typeflag {
case tar.TypeDir:
// handle directory
fmt.Println("Creating directory :", filename)
// or use 0755 if you prefer
err = os.MkdirAll(filename, os.FileMode(header.Mode))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
case tar.TypeReg:
// handle normal file
fmt.Println("Untarring :", filename)
writer, err := os.Create(filename)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
io.Copy(writer, tarBallReader)
err = os.Chmod(filename, os.FileMode(header.Mode))
if err != nil {
fmt.Println(err)
os.Exit(1)
}
writer.Close()
default:
fmt.Printf("Unable to untar type : %c in file %s", header.Typeflag,
filename)
}
}
}
If you have python installed you can find this code handy:
$path = 'C:\yourPythonFile.py'
$str = "import tarfile",
"tar = tarfile.open(""C:/yourTarFile.tar"")",
"tar.extractall(""."")",
"tar.close()"
[System.IO.File]::WriteAllLines($path, $str)
cd C:\
python yourPythonFile.py

Get the value of an input field in IE using AHK

I'm trying to get the value on an input field in IE using auto hot key.
I'm using AHK version 1.1.19.01 on windows 8.1 using IE 11.0.9600.17498
I have a simple (local) html page:
<!DOCTYPE html>
<html>
<head>
<title>Page1</title>
</head>
<body>
<input type="text" name="area2" id="area2" />
</body>
</html>
I type something in the text box and then run the ahk script (which should just tell me the value I typed in).
This is my ahk script:
wb := IEGet("Page1")
WinActivate Page1
txt := wb.Document.All.area2.Value
MsgBox % txt
IEGet(Name="") ;Retrieve pointer to existing IE window/tab
{
IfEqual, Name,, WinGetTitle, Name, ahk_class IEFrame
{
Name := ( Name="New Tab - Windows Internet Explorer" ) ? "about:Tabs" : RegExReplace( Name, " - (Windows|Microsoft) Internet Explorer" )
}
For wb in ComObjCreate( "Shell.Application" ).Windows
{
If ( wb.LocationName = Name ) && InStr( wb.FullName, "iexplore.exe" )
{
Return wb
}
}
}
The message box is blank.
I have tried various syntax to no avail. What am I doing wrong?
The IEGet function was copied from some web page - its not mine, but it works.
NOTES:
To find the ahk version:
msgbox % "my ahk version: " A_AhkVersion
Here is a simple working example ( win7 v1.1.19.01 IE11 )
FileSelectFile, path
wb := ComObjCreate("InternetExplorer.Application")
wb.visible := true
wb.navigate(path)
while wb.readyState!=4 || wb.document.readyState != "complete" || wb.busy
continue
return
f6::
msgbox % wb.document.all["area2"].value
return
I have sometimes also had problems with IEGet() and IE9+
but here is the function I use to get an active IE Object
WBGet(WinTitle="ahk_class IEFrame", Svr#=1) { ;// based on ComObjQuery docs
static msg := DllCall("RegisterWindowMessage", "str", "WM_HTML_GETOBJECT")
, IID := "{0002DF05-0000-0000-C000-000000000046}" ;// IID_IWebBrowserApp
;// , IID := "{332C4427-26CB-11D0-B483-00C04FD90119}" ;// IID_IHTMLWindow2
SendMessage msg, 0, 0, Internet Explorer_Server%Svr#%, %WinTitle%
if (ErrorLevel != "FAIL") {
lResult:=ErrorLevel, VarSetCapacity(GUID,16,0)
if DllCall("ole32\CLSIDFromString", "wstr","{332C4425-26CB-11D0-B483-00C04FD90119}", "ptr",&GUID) >= 0 {
DllCall("oleacc\ObjectFromLresult", "ptr",lResult, "ptr",&GUID, "ptr",0, "ptr*",pdoc)
return ComObj(9,ComObjQuery(pdoc,IID,IID),1), ObjRelease(pdoc)
}
}
}
It Query's the IWebBrowserApp interface and returns a usable IE Comobject
SetTitleMatchMode, 2
wb := WBGet("Page1")
txt := wb.Document.All["area2"].value
MsgBox % txt
Hope it helps