Unicode named Folder shows ? in wscript prompt - unicode

I am facing problems with Unicode named folders. When I drag the folder to the script, it doesn't show the path of the folder properly.
Simple VBScript (this is just a portion of it):
Dim Wshso : Set Wshso = WScript.CreateObject("WScript.Shell")
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
If FSO.FileExists(Wscript.Arguments.Item(0)) = true and FSO.FolderExists(Wscript.Arguments.Item(0)) = false Then
Alert "You dragged a file, not a folder! My god." & vbcrlf & "Script will terminate immediately", 0, "Alert: User is stupid", 48
WScript.Quit
Else
targetDir = WScript.Arguments.Item(0)
Wshso.Popup targetDir
End If
Else
targetDir = Wshso.SpecialFolders("Desktop")
Alert "Note: No folder to traverse detected, default set to:" & vbcrlf & Wshso.SpecialFolders("Desktop"), 0, "Alert", 48
End If
If it is a normal path without Unicode characters, it's fine. But in this case:
Directory: 4minute (포미닛) - Hit Your Heart
Then it will show something like 4minute (?) - Hit Your Heart
And if I do a FolderExists it can't find the dragged folder.
Is there any workaround to support Unicode named Folders?
Thanks!
I'll edit if this is not clear enough

This does seem to be a problem peculiar to the Windows Script Host's DropHandler shell extension. Whereas:
test.vbs "C:\포미닛.txt"
C:\WINDOWS\System32\WScript.exe "test.vbs" "C:\포미닛.txt"
both work when typed from the console (even if the console can't render the Hangul so it looks like ?), a drag and drop operation that should result in the same command goes through a Unicode->ANSI->Unicode translation that loses all characters that aren't in the current ANSI code page. (So 포미닛 will work on a default Korean Windows install but not Western.)
I'm not aware of a proper way to fix the problem. You could perhaps work around it by changing the DropHandler for .vbs files in the registry:
HKEY_CLASSES_ROOT\VBSFile\ShellEx\DropHandler\(Default)
from the WSH DropHandler ({60254CA5-953B-11CF-8C96-00AA00B8708C}) to {86C86720-42A0-1069-A2E8-08002B30309D}, the one used for .exe, .bat and similar, which doesn't suffer from this issue. You would also probably have to change the file association for .vbs to put quotes around the filename argument too, since the EXE DropHandler doesn't, to avoid problems with spaces in filenames.
Since this affects argument-passing for all VBS files it would be a perilous fix to deploy on any machine but your own. If you needed to do that, maybe you could try creating a new file extension with the appropriate DropTarget rather than changing VBSFile itself? Or maybe forgo drop-onto-script behaviour and provide a file Open dialog or manual drop field instead.

For anyone landing here from Google...
Bobince's tip lead me to work around this problem by wrapping my vbscript file (myscript.vbs) in a dos batch file (mybatch.bat).
The tip was:
"Seem to be a problem peculiar to the Windows Script Host's
DropHandler shell extension whereas.... the one used for .exe, .bat and
similar... doesn't suffer from this issue."
mybatch.bat contains:
:Loop
IF "%1"=="" GOTO Continue
set allfiles=%allfiles% "%1"
SHIFT
GOTO Loop
:Continue
"myscript.vbs" %allfiles%
You may also find this code from my myscript.vbs to be helpful
For Each strFullFileName In Wscript.Arguments
' do stuff
Next

Based on DG's answer, if you just want to accept one file as drop target then you can write a batch file (if you have it named as "x.bat" place VBScript with filename "x.bat.vbs" at same folder) that just contains:
#"%0.vbs" %1
the # means to not output the row on the display (I found it to show garbage text even if you use chcp 1250 as first command)
don't use double-quotes around %1, it won't work if your VBScript uses logic like the following (code I was using below was from http://jeffkinzer.blogspot.com/2012/06/vbscript-to-convert-excel-to-csv.html). Tested it and it works fine with spaces in the file and folder names:
Dim strExcelFileName
strExcelFileName = WScript.Arguments.Item(0) 'file name to parse
' get path where script is running
strScript = WScript.ScriptFullName
Dim fso
Set fso = CreateObject ("Scripting.FileSystemObject")
strScriptPath = fso.GetAbsolutePathName(strScript & "\..")
Set fso = Nothing
' If the Input file is NOT qualified with a path, default the current path
LPosition = InStrRev(strExcelFileName, "\")
if LPosition = 0 Then 'no folder path
strExcelFileName = strScriptPath & "\" & strExcelFileName
strScriptPath = strScriptPath & "\"
else 'there is a folder path, use it for the output folder path also
strScriptPath = Mid(strExcelFileName, 1, LPosition)
End If
' msgbox LPosition & " - " & strExcelFileName & " - " & strScriptPath

Modify WSH DropHandler ({60254CA5-953B-11CF-8C96-00AA00B8708C}) to {86C86720-42A0-1069-A2E8-08002B30309D} and add this function to convert short path to long:
Function Short2Long(shortFullPath)
dim fs
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFile(shortFullPath)
Set app = CreateObject("Shell.Application")
Short2Long = app.NameSpace(f.ParentFolder.Path).ParseName(f.Name).Path
end function

Related

How to include OS command with Substitute function in Openedge?

Im trying to create an PDF via OS-Command in OpenEdge but I hit an error when I run the script.
*Error : The command "C: \ Program" is either misspelled or could not be found
It works perfectly :
os-command (' "C:\Program Files (x86)\wkhtmltopdf\wkhtmltopdf.exe"
"V:\V11\WEB\PDF\Name_01.03.2021_14.09.30_da.html"
"V:\V11\WEB\PDF\Name_01.03.2021_14.09.30_da.pdf" ').
However, when I Include the command in script and run it then I encounter an error.
This one doesnt work :
define variable cmdcommand as char no-undo. cmdcommand = SUBSTITUTE
(' "C:\Program Files (x86)\wkhtmltopdf\wkhtmltopdf.exe"
"V:\V11\WEB\PDF\Name_&1_&2_&3.html"
"V:\V11\WEB\PDF\Name_&1_&2_&3.pdf" ', "01.03.2021", "14.09.30", "da").
os-command value(cmdcommand).
What did I miss here? Can anyone help?
After having fought with os-command for quite some time to get normal errors and output returned, if you are only targeting Windows then it you may find it easier to use the .Net System.Diagnostics.Process class.
To get you started:
define variable oProcess as System.Diagnostics.Process no-undo.
define variable oInfo as System.Diagnostics.ProcessStartInfo no-undo.
oProcess = new System.Diagnostics.Process().
assign
oInfo = oProcess:StartInfo
oInfo:FileName = "C:~\Program Files (x86)~\winmerge~\winmergeu.exe".
oInfo:WorkingDirectory = "session:temp-directory
oInfo:Arguments = substitute(
"&1 &2",
quoter( "file1.txt" ),
quoter( "file2.txt" )
)
.
oProcess:Start().
oProcess:WaitForExit().
Other useful properties of the ProcessStartInfo class include:
CreateNoWindow
UseShellExecute
RedirectStandardError
RedirectStandardOutput
In your second sample, there's no value in using SUBSTITUTE, as your're not using place holders (&1, &2, ...). What you're doing is basically a straight forward string assignment.
The resulting string looks like this:
"C:\Program Files (x86)\wkhtmltopdf\wkhtmltopdf.exe""V:\V11\WEB\PDF\Name_01.03.2021_14.09.30_da.html""V:\V11\WEB\PDF\Name_01.03.2021_14.09.30_da.pdf"
there's an extra space at the beginning
there's no space between the closing quote of the path to your exe and the first argument.
This here works for me:
define variable cmdcommand as char no-undo.
cmdcommand = SUBSTITUTE ('"c:\Program Files (x86)\WinMerge\winmergeu.exe" &1 &2',
"c:\temp\1.txt",
"c:\temp\2.txt").
OS-COMMAND silent value(cmdcommand).
Due to the use of the SUBSTITUTE function with place holders, this gives me a clean command with a space between the exe path and the first argument.
It works with or without the SILENT option.

Why is PowerShell typing chinese characters into my files?

I'm trying to make a system which turns the contents of a .txt file into a variable. This isn't my problem, though; for some reason, my files are reading characters I didn't enter, and can't use.
Please note: What I'm doing is in no way efficient, and I'm positive there are other ways to go about this, but this is the best way for me. Also, I'm not amazingly intelligent when it comes to coding. Just thought I'd throw that out there.
First, let me show you the system I have in place.
value.txt
4
This file has the contents which I'd like to make into a variable.
Batch Files
setcmdvar.bat
set cmdvar=
I leave this empty so that I can put the contents of value.txt at the end (more on this later).
start.bat
#echo off
call PowerShell.exe cd "C:\Users\%username%\Desktop\Folder"; $PSvar = Get-Content value.txt; $PSvar >> setcmdvar.bat
pause
call setcmdvar.bat
pause
echo The variable equals %cmdvar%.
pause
exit
The second line from start.bat creates this script in PowerShell:
PowerShell script
cd "C:\Users\%username%\Desktop\Folder\"
$PSvar = Get-Content value.txt; $PSvar >> setcmdvar.bat
This creates a variable in PowerShell, $PSvar, which equals the contents of value.txt; in our case, 4. Then, it puts $PSvar (4) at the end of setcmdvar.bat, using >>, which changes it to:
setcmdvar.bat (changed)
set cmdvar=4
Or, at least, it should, to my knowledge. Instead, it changes the file to this:
set Items=桔⁥瑳楲杮椠⁳業獳湩⁧桴⁥整浲湩瑡牯›⸢ †⬠䌠瑡来牯䥹普††††㨠倠牡敳䕲牲牯›㨨
嵛‬慐敲瑮潃瑮楡獮牅潲割捥牯䕤捸灥楴湯 †⬠䘠汵祬畑污晩敩䕤牲牯摉㨠吠牥業慮潴䕲灸捥整䅤䕴摮晏瑓楲杮 
Or some other strange combination of characters. I looked one up, and it was Chinese. There's also some other characters like †, ⬠, ›, ⸢, 
, and ⁳. I have no idea why these are being typed. Along with this, start.bat displays the following:
Press any key to continue . . .
(PowerShell script runs here)
'■s' is not recognized as an internal or external command,
operable program or batch file.
Press any key to continue . . .
The variable equals .
Press any key to continue . . .
(exit)
I did not type "■s," and I assume this may be the problem. Whatever it is, does anyone have any ideas?
P.S. I'm sorry if my code is complicated, or if it looks bad, but I have it this way for a reason. Mostly my incompetence, actually. But I think it's better that way.
Also, I know there are commands like for /f "delims=" %a in ('ver') do #set foobar=%a (I just took this off the internet) but I've tried commands like those, and I suppose I just don't understand them all that well, because they didn't work.
I appreciate the help!
It would probably be better to avoid the static setcmdvar.bat script and write it all in the script. Using -Encoding ascii is what keeps the output from being Unicode and having a BOM (Byte Order Mark) at the beginning. It has nothing to do with Chinese characters.
ECHO>"%USERPROFILE%\value.txt" 4
SET "CMDFILE=%USERPROFILE%\setcmdvar.bat"
powershell -NoLogo -NoProfile -Command ^
"'SET ""cmdvar=' + (Get-Content $Env:USERPROFILE\value.txt) + '""""' |" ^
"Out-File -FilePath %CMDFILE% -Encoding ascii"
pause
call "%CMDFILE%"
pause
echo The variable equals %cmdvar%
pause
EXIT /B 0
>> has its problems with mixing encodings. Plus it defaults to utf16. I recommend changing
$PSvar >> setcmdvar.bat
to
add-content setcmdvar.bat $PSvar
I'm not sure how to keep everything on one line. You can make setcmdvar.bat like this:
set cmdvar=^
So that it continues.

AutoHotKey - How to take a screenshot and to paste it to a *.jpg file?

How to take a screenshot in Windows 8 and to paste it to a *.jpg file using AutoHotKey script? I want my custom key combination and folder for images
{CustomKey}:: ;image saved in Pictures/Screenshots folder by default
Send #{PrintScreen}
Return
The images are saved as png; can then be converted to jpg and moved to another directory.
Tested in Win 10.
Might work in Win 8 too.
Another question similar asked here:
https://autohotkey.com/board/topic/63742-how-to-save-a-screen-shot-with-ahk/
Problem was that saved file was blank. In my case, the file turned out to be all grey.
Reason was that FileAppend saved as text file.
To save screenshot image taken with PrintScrn button:
; Send {PrintScreen}
FileAppend %ClipboardAll%, FileName.raw, UTF-8
; This can be read back to memory with:
FileRead, Clipboard, *c FileName.raw
; image can also be converted/compressed to save space.
; I already had ffmpeg, so put this:
Run %ComSpec% /c "ffmpeg.exe -f rawvideo -pixel_format rgb32 -s 2256x1504 -i FileName.raw -vf hflip -vf vflip output.png"
Tested on Win 10.
You might try using the Gdip_All.ahk library. I found a maintained version of it at: https://github.com/mmikeww/AHKv2-Gdip/blob/master/Gdip_All.ahk
If you have Irfan View installed you can use this:
run('"C:\Program Files\IrfanView\i_view64.exe" /capture=0 "/convert=path_to_file.png" /jpgq=95')
You can also specify format or quality and include process name, time or other staff, for example:
dir := 'D:\screenshots'
name := winGetProcessName('A') ' ' a_YYYY '-' a_MM '-' a_DD ' ' a_hour '-' a_min '-' a_sec
format := 'png'
quality_jpeg := 95
run('"C:\Program Files\IrfanView\i_view64.exe" /capture=0 "/convert=' dir '\' name '.' format '" /jpgq=' quality_jpeg)
You can check Irfan View command line options in the program help or here.
You can also search some other programs that can silently make screenshots using command line options. If you find another good one let me know.

Two tasks in Vb Script overlapping?

I am new to VB Script, but since it is straight forward, so I grabbed two fragments of code from the web and combine them into one in order to do my task.
Basically what I want is to run an application called "MapForce.exe" and produce an output file, then create a new directory and copy this file to this new directory too.
The code is straightforward:
'This is the line to call MapForce.exe and produce output file.
createObject("wscript.shell").exec "C:\Program Files\Altova\MapForce2011\MapForce.exe 834toASCII.mfd /BUILTIN /LOG ACS.log"
'These are the lines to copy that output file to the new folder:
sourceDir = "C:\Documents and Settings\Robert\test\result.txt"
destinationDir = "C:\Documents and Settings\Robert\test\"
const OverwriteExisting = True
strDirectory = destinationDir & replace(Month(date),"/","_") & " TOU"
Set fso = CreateObject("Scripting.FileSystemObject")
if not fso.FolderExists(strDirectory) then
Set objFolder = fso.CreateFolder(strDirectory)
end if
fso.CopyFile sourceDir & "*.*", strDirectory & "\", OverwriteExisting
Now it works: Mapforce.exe gets run, output generated, new folder created and a file copied to the new folder. But the question is, since the MapForce will take a longer time to finish and produce the newest output file, so line 1 takes longer time to finish, however, the remaining lines of doing copying task don't wait for it to finish, so the file gets copied in the new folder is always the old one, not the newest one generated by the application.
To put it in another way, the remaining lines hurry to finish the task without caring whether the first line (which runs the MapForce application) finishes or not.
So I wonder if experts could give me advice on how to force the remaining lines to wait for the first line gets finished and newest output gets generated?
You could use the WshShell.Run method.
The first parameter (REQUIRED) is the executable (including parameters).
The second parameter (OPTIONAL) specifies the window style.
The third parameter (OPTIONAL) specifies whether the scripts waits for the command to complete before continuing.
A sample:
Dim oShell
Set oShell = WScript.CreateObject("WScript.Shell")
returnCode = oShell.Run("Your.exe Param1 Param2", 1, True)

Batch File to Determine Modified Dates

Hey guys, I'm looking for a batch file to tell me if certain folders have been modified today (I'll run it every morning). I'm happy to specify each of the folders to be to be queried, I just haven't been able to find anything that meets my requirements yet. If anyone knows off the top of their head what the code for the .bat would be, that would be awesome :) Thanks in advance.
Here's a batch file that should do the trick:
#echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
for /D %%Q IN (*.*) DO (
set FILETIME=%%~tQ
if "!FILETIME:~0,10!"=="%DATE:~4%" echo %%Q
)
This works by comparing the date-part of the file timestamp against the current date.
As written, it checks directories in the current directory, but you could replace *.* with whatever filespec you want to test (or pass it in as an argument).
I don't know if this will work on systems with anything other default English/US regional settings, but it could probably be tweaked to make it work, if it doesn't already. I also don't know what would happen if the system is shared between users in different time-zones.
you can use a vbscript
Set objFS = CreateObject( "Scripting.FileSystemObject" )
strFolder = WScript.Arguments(0)
Set objFolder = objFS.GetFolder(strFolder)
If DateDiff("d", Now, objFolder.DateLastModified ) = 0 Then
WScript.Echo "0"
End If
in your batch file (or command line)
C:\test>cscript //nologo test.vbs myFolderName
use a for loop to catch the output. (Or you can even do everything in vbscript )