I'm trying to create named pipe using VBScript on win7.
This is my code (took from there):
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile("\\.\pipe\PipeName", True)
a.WriteLine("This is a test.")
a.Close
But i got an error (manual translate, so may be not accurate):
test.vbs(2, 1) Microsoft VBScript runtime error: File not found
Same code with ordinary text file works fine:
Set a = fs.CreateTextFile(".\\PipeName", True)
But, when i tried to escape backslashes:
Set a = fs.CreateTextFile("\\\\.\\pipe\\PipeName", True)
I got:
test.vbs(2, 1) Microsoft VBScript runtime error: Path not found
UPD: I run script as administrator.
UPD2: I'm found another solution for my problem without using pipes, so my question is a little outdated, but I don't know what to do with it.
Did you create a named pipe server called 'PipeName'? This code works for me (I named my pipe 'HelloWorld'):
C# Server:
static void Main(string[] args)
{
using (var pipe = new NamedPipeServerStream("HelloWorld"))
{
pipe.WaitForConnection();
StreamReader reader = new StreamReader(pipe);
var line = reader.ReadLine();
Console.WriteLine(line);
}
Console.ReadLine();
}
VBScript Client:
Dim fs, pipe
Set fs = CreateObject("Scripting.FileSystemObject")
Set pipe = fs.OpenTextFile("\\.\pipe\HelloWorld", 8, False, 0)
pipe.WriteLine("This is my message")
pipe.Close
I tried to work with named pipe from VBScript. I failed to create named pipe by fso.CreateTextFile("\\.\pipe\MyPipe").
But I successfully connected from VBScript from with Pipe created by classical application:
Pipe was created by such code (pascal):
procedure OpenTestPipe;
var
i,hOut: Integer;
begin
hOut:=CreateNamedPipe('\\.\pipe\Test.htm',PIPE_ACCESS_OUTBOUND,PIPE_TYPE_BYTE,PIPE_UNLIMITED_INSTANCES,1024,1024,NMPWAIT_USE_DEFAULT_WAIT,nil);
i:=FileWrite(hOut,'Hello'#13#10,7);
MessageBox(0,'Pipe is opened','Pipe sample',0);
FileClose(hOut);
end;
When MessageBox was shown I opened VBScript
Set fso = CreateObject("Scripting.FileSystemObject")
MsgBox fso.OpenTextFile("\\.\pipe\test.htm",1).readLine
And got a message Hello
Related
I need to start a process and have access to the PID, so I am trying to use ShellExecuteEx. I am attempting to open a batch file. However, no matter how I pass the parameters and no matter where the file is located and what permission's I have on the file, the function is returning with Error Code 5: Access is denied.
The File is located in the same location as the config files that have already been read successfully.
The File is set for full access permissions with any user.
It does this with any file type. I've tried just opening text files with the same outcome (Error 5)
If I use ShellExecute() instead, the batch file is run successfully.
Here is some of the code I've tried:
SHELLEXECUTEINFO exInfo;
exInfo.cbSize = sizeof(SHELLEXECUTEINFO);
exInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
exInfo.lpVerb = "open";
exInfo.lpFile = "C:\\batchtest.bat";
exInfo.nShow = SW_NORMAL;
BOOL hReturnCode = ShellExecute(&exInfo);
DWORD LastError = GetLastError();
I've also tried:
SHELLEXECUTEINFO exInfo;
exInfo.cbSize = sizeof(SHELLEXECUTEINFO);
exInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
exInfo.lpVerb = "open";
exInfo.lpFile = "C:\\Windows\\system32\\cmd.exe";
exInfo.lpParameters = "batchtest.bat";
And many variations of the above.
Also, I've tried something really simple like from here:
Get PID from ShellExecute
to no avail.
However this:
ShellExecute(NULL, "open", "C:\\testbat.bat", NULL, NULL, SW_SHOWNORMAL);
works without an error. Unfortunately, I need the PID, so I can't use ShellExecute.
Any suggestions would be greatly appreciated. I feel like I've exhausted all of my options.
Environment:
VS 2008
Windows 7
EDIT: fixed the code to "C:\batchtest.bat"; as suggested. (Still same result)
Figured it out.
In order to run batch file and I guess some other types of exe's on Windows 7, you have to elevate the call using the lpVerb = _TEXT("runas") -- even if you have UAC turned off. This isn't documented in the SHELLEXECUTEINFO structure documentation on MDSN (it isn't even given as an option), since it says: "The following verbs are commonly used"
The final code was as follows:
SHELLEXECUTEINFO exInfo;
exInfo.cbSize = sizeof(SHELLEXECUTEINFO);
exInfo.fMask = SEE_MASK_NOCLOSEPROCESS; //allows the PID to be returned
exInfo.hwnd = NULL;
exInfo.lpVerb = _TEXT("runas"); //elevates for Windows 7
exInfo.lpFile = "C:\\BatchTest.bat";
exInfo.lpParameters = NULL;
exInfo.nShow = SW_MAXIMIZE;
exInfo.hInstApp = NULL;
exInfo.lpDirectory = NULL;
BOOL hReturnCode = ShellExecuteEx(&exInfo);
I hope that helps others out.
Shouldn't the line
exInfo.lpFile = "C:\\batchtest.exe";
be
exInfo.lpFile = "C:\\batchtest.bat";
I have a windows app that prints pdfs directly to a printer. Everything is working but for some reason for each pdf to print I see the pdf reader Nitro Pro pop up in the background then close.
Is there a way to keep the window from poping up. It does not seem to effect the over application but just kind of annoying.
private void PrintDocument(string printer, string fileName)
{
ProcessStartInfo info = new ProcessStartInfo
{
Arguments = "\"" + printer + "\"",
Verb = "PrintTo",
FileName = fileName,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true
};
Process p = new Process { StartInfo = info };
p.Start();
p.WaitForExit(5000);
if (p.HasExited == false)
{
p.Kill();
}
}
This is not possible.
Windows can't print a file directly, it relies on a program to do so. It will use whatever application has configured itself to handle the PrintTo verb for the particular file extension. In your case it appears the application is Nitro Pro.
It's possible that you can find and install an application that can print the file without opening a window to do so, but that's beyond the scope of StackOverflow.
VBscript example:
Function ADO_WriteToFile(FileURL,data)
Dim arrBytes
SET ADObj = CreateObject("ADODB.Stream")
ADObj.Open
ADObj.Charset = "iso-8859-1"
ADObj.Type = adTypeText
ADObj.WriteText data
ADObj.SaveToFile FileURL, adSaveCreateOverwrite
ADObj.Close
ADObj.Open
ADObj.Type = adTypeBinary
ADObj.LoadFromFile FileURL
ADObj.Position = 3
arrBytes = ADObj.Read
ADObj.Position = 0
ADObj.SetEOS
ADObj.Write data
ADObj.SaveToFile FileURL, adSaveCreateOverwrite
ADObj.Close
End Function
JScript example:
function writeTo(fileName,str) {
var ado = new ActiveXObject("ADODB.Stream");
ado.Type = 2;
ado.Open();
ado.Position = 0;
ado.WriteText(str,0);
ado.SaveToFile(fileName,2);
ado.Close();
ado.Open();
ado.Type = 1;
ado.Position = 2;//line 19
var temp = ado.Read();
ado.Position = 0;
ado.SetEOS;
ado.Write(temp);
ado.SaveToFile(fileName,2);
ado.Close();
}
Why does the VBScript example work perfectly except for the fact that it can't accept file paths with space in them?
The JScript example errors out with the message "assignment to the parameter is incorrect." line 19. This doesn't happen if I set Position to 0 however:
ado.Position = 0;
i am using this to write binary files to disk btw
Here are some differences:
In the VBScript version, position is set to 3; in the JScript version, it is set to 2
In the VBScript version, the character set is defined; in the JScript version, it is undefined
In the VBScript version, WriteText and write both reference the argument; in the JScript version, only WriteText references it
References
Use vs Mention in JScript doesn't come for Free
JScript Data Types: Data Type Summary
I am reading a name of the file/script from an utf-8 encoded XML file. This is then passed to VBScript. VBScript starts a second program to which this passed program/script is provided as an argument. When the argument is in English, the VBScript executes successfully.
But if the name read from XML is non-english( Russian in my case ), VBScript fails to find that file.
I am running VBScript from Java code only using "cscript" as I am running it on Windows.
However, if I copy the command fired by Java program to run VBScript, and paste it on command prompt, it executes normally despite the argument name is in non-english language.
I then hardcoded file/script name in VBScript. Changed encoding of VBScript to UCS2-LE, and directly run it from command prompt. It executed normally. It failed to execute for any other encoding used for VBScript. Also the non-english text is displayed as ? in any other encoding than UCS2-LE.
Then I tried to encode file/script name into UTF16-LE in Java and then passed it to VBScript. Irrespective of which encoding was used in VBScript, it fails. Again if I copy the command printed on standard output from Java program and run it from cmd, it executes.
The command printed from Java displays non-english text correctly.
Can anyone please help me to resolve the issue?
Any relative help would be greatly appreciated.
This is what I am doing currently. I need to pass an argument contatining Russian Text to VBScript from Java.
I tried to use two different approaches.
First approach in the code below writes the Russian text in a file using encoding UnicodeLittle. File is found to be in encoding UCS-2LE. And then VBScript reads the value from that file, and script is executed successfully.
In second approach, I tried to directly pass encoded Russian text as argument to script. VbScript fails saying that script can't be opened.This is the approach I want solution for.
Below is the Java code attached.
Any help would be greatly appreciated.
public class CallProgram
{
private static String encodeType = "UnicodeLittle";
private File scriptName = new File( "F:\\Trial Files\\scriptName.txt" );
public static void main(String[] args)
{
CallProgram obj = new CallProgram();
Runtime rt = Runtime.getRuntime();
try
{
**//Approach1 - Writes text to file and calls vbscript which reads text from file and uses it as an argument to a program**
String sName = "D:\\CheckPoints_SCRIPTS\\Менеджер по качеству"; //Russian Text
byte [] encodedByte= sName.getBytes( encodeType );
String testCase = new String( encodedByte, encodeType ); //New string containing russian text in UnicodeLittle encoding...
obj.writeToFile( testCase ); //Writing russian string to file...
String mainStr = "cscript /nologo \"D:\\Program Files\\2.0.1.3\\Adapter\\bin\\scriptRunner_FileRead_Write.vbs\"";
Process proc1 = rt.exec( mainStr );
int exit = proc1.waitFor();
System.out.println( "Exit Value = " + exit );
**//Approach 2 - Passing encoded Russian text directly to VbScript...**
//This is not working for me...
String [] arrArgs = { "cscript", "/nologo", "\"D:\\Program Files\\IBM\\Rational Adapters\\2.0.1.3\\QTPAdapter\\bin\\scriptRunner.vbs\"", testcase };
ProcessBuilder process = new ProcessBuilder( arrArgs );
Process proc2 = process.start();
proc2.waitFor();
}
catch (IOException e)
{
e.printStackTrace();
}
catch ( InterruptedException intue )
{
intue.printStackTrace();
}
}
//Function to write Russian text to file using encoding UnicodeLittle...
private void writeToFile( String testCase )
{
FileOutputStream fos = null;
Writer out = null;
try
{
fos = new FileOutputStream( this.scriptName );
out = new OutputStreamWriter( fos, encodeType );
out.write( testCase );
out.close();
fos.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch ( IOException ioe )
{
ioe.printStackTrace();
}
finally
{
try
{
if ( fos != null )
{
fos.close();
fos = null;
}
if ( out != null)
{
out.close();
out = null;
}
}
catch( IOException ioe )
{
fos = null;
out = null;
}
}
} // End of method writeToFile....
}
I've resolved similar problems before by using the short 8.3-style filename instead of the long filename. I get this short name using the ShortPath method of FileSystemObject. Here's a VBScript example... you may want to try something similar in Java.
Function GetShortPath(strLongPath)
Dim FSO
Dim objFolder
Dim objFile
Dim strShortPath
Set FSO = CreateObject("Scripting.FileSystemObject")
' Is it a file or a folder?
If FSO.FolderExists(strLongPath) Then
' It's a folder.
Set objFolder = FSO.GetFolder(strLongPath)
strShortPath = objFolder.ShortPath
ElseIf FSO.FileExists(strLongPath) Then
' It's a file.
Set objFile = FSO.GetFile(strLongPath)
strShortPath = objFile.ShortPath
Else
' File not found.
strShortPath = ""
End If
GetShortPath = strShortPath
End Function
For example,
Debug.Print GetShortPath("C:\öêåéèüø.çõâ")
returns C:\B373~1, which can be used in place of the long filename with non-English characters. Example with dir /x (reveals the short filename) and notepad:
C:\sandbox>dir /x
Volume in drive C has no label.
Volume Serial Number is BC90-DF37
Directory of C:\sandbox
13/01/2011 15:12 <DIR> .
13/01/2011 15:12 <DIR> ..
13/01/2011 14:52 22 NEWTEX~1.TXT New Text Document.txt
13/01/2011 15:05 0 C7F0~1.TXT öêåéèüø.txt
13/01/2011 15:05 0 B373~1 öêåéèüø.çõâ
3 File(s) 22 bytes
2 Dir(s) 342,158,913,536 bytes free
C:\sandbox>notepad B373~1
I've got a Windows XP batch script which cleans some directories, but I would like to move the deleted files to trash instead of using plain del. How is this done?
It looks like the only languages I can use for this is plain batch or Perl.
use Win32::FileOp qw(Recycle);
Recycle(#ARGV);
Write a VBS script (Original Link) then call it with MyDelScript.vbs
function main()
{
if (WScript.Arguments.length != 1)
{
WScript.Echo("<Insert informative error message here>");
return;
}
var Path = WScript.Arguments(0);
var Shell = WScript.CreateObject("Shell.Application");
var Item = Shell.Namespace(0).ParseName(Path);
Item.InvokeVerb("delete");
}
The Win32::FileOp module has a Recycle function. From the docs:
Recycle #filenames
Send the files into the recycle bin. You will not get any confirmation dialogs.
Returns true if successful.
It can be done like this with plain batch and embedded VBScript. Put the following code into a file called recycle.cmd:
<!-- : Begin batch script
#echo off
if "%1"=="" (
echo Usage: %~nx0 FILE_TO_RECYCLE[...]
echo This script puts files into the recycle bin
exit /b 1
)
cscript //nologo "%~f0?.wsf" %*
exit /b %errorlevel%
----- Begin embedded wsf script --->
<job><script language="VBScript">
Set app = WScript.CreateObject("Shell.Application")
Set fso = CreateObject("Scripting.FileSystemObject")
For Each arg In WScript.Arguments
If fso.FileExists(arg) Then
Set file = fso.GetFile(arg)
Set folderItem = app.Namespace(0).ParseName(file.Path)
folderItem.InvokeVerb("delete")
Else
WScript.Echo "File not found: " & arg
End If
Next
</script></job>
Example:
echo This file is dirt.> dirt.txt
echo This file is trash.> trash.txt
recycle dirt.txt trash.txt
As you can see the script allows recycling multiple files with one command.
It does not suppport the wildcards * and ? though.
The idea of embedding VBScript inside a batch file is taken from dbenham's answer to Is it possible to embed and execute VBScript within a batch file without using a temporary file? (scroll down to UPDATE 2014-04-27).
You could use the "recycle" utility which is part of CmdUtils from MaDdoG Software. From the page listing -
Recycle, a safe replacement for the DEL command, that sends files to the recycle bin instead of deleting them. Recycle is also more flexible than DEL; you can specify multiple files at once (or use wildcards), and you can recycle whole directories at once (be careful!)
I would suggest you try its various switches before you incorporate it into your script - there is quite a bit of deviation from the default behaviour of the "del" command.
UPDATE: Contrary to my original claim that the following code does not work, it indeed seems to work. I just forgot that the file I wanted to delete was not in $ENV{TEMP} but a subdirectory of $ENV{TEMP}. The problem is, the file does not go to the Recycle Bin.
The right solution is to use Win32::FileOp but I am going to leave this script here as an example of how to use Win32::API and Win32::API::Struct. I would appreciate it if anyone can point out what I am doing wrong. For your reference:
SHFileOperation: http://msdn.microsoft.com/en-us/library/bb762164(VS.85).aspx
LPSHFILEOPSTRUCT: http://msdn.microsoft.com/en-us/library/bb759795(VS.85).aspx
#!/usr/bin/perl
use strict;
use warnings;
use File::Spec::Functions qw( catfile );
use Win32::API;
Win32::API::Struct->typedef(
SHFILEOPSTRUCT => qw(
HWND hwnd;
UINT wFunc;
LPCTSTR pFrom;
LPCTSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCTSTR lpszProgressTitle;
)
);
Win32::API->Import(
shell32 => q{ int SHFileOperation( LPSHFILEOPSTRUCT lpFileOp ) }
);
my $op = Win32::API::Struct->new( 'SHFILEOPSTRUCT' );
$op->{wFunc} = 0x0003; # FO_DELETE from ShellAPI.h
$op->{fFlags} = 0x0040; # FOF_ALLOWUNDO from ShellAPI.h
my $to_delete = catfile( $ENV{TEMP}, "test.file" );
$op->{pFrom} = $to_delete . "\0\0";
my $result = SHFileOperation( $op );
if ( $result ) {
warn sprintf "The operation failed: %4.4X\n", $result;
}
else {
if ( $op->{fAnyOperationsAborted} ) {
warn "Operation was aborted\n";
}
else {
warn "The operation succeeded\n";
}
}
__END__