Write binary data using javascript on the server - asp-classic

I'm trying to output a PDF using server side javascript (ASP). The current method I'm using is:
xfile=Server.MapPath(lib.fso.GetTempName())
xf=lib.fopen(xfile,"wb");
lib.fwrite(xf,this.buffer);
lib.fclose(xf);
outB = Server.CreateObject("ADODB.Stream")
outB.Type = 1
outB.Open()
outB.LoadFromFile (xfile)
Response.BinaryWrite(outB.Read())
outB.Close()
lib.fso.DeleteFile(xfile);
This works, but requires write access on the server. Is there a way to do the same thing without writing to a file?
I havn't been able to figure out how to convert the string this.buffer into a array of byte that I can then write using Response.BinaryWrite without writing to a file first.

Why not simply use:-
Response.Write(this.buffer)
Assuming the codepage of the response is set correctly (I.e., its the same as in the Locale that the VBScript is running in) then Response.Write should do the same conversion that your StringToMultiByte is doing.
I suspect you've tried this and is hasn't worked. If so I really think you need to look into why that is rather attempt this strange usage of BinaryWrite. Currently your solution is going to kill your server.

My solution was to use VBScript.
replace the above code with:
Response.BinaryWrite(StringToMultiByte(this.buffer));
and add this to the end of the file:
<script language="vbscript" runat="server">
function StringToMultiByte(S)
Dim i, MultiByte
For i=1 To Len(S)
MultiByte = MultiByte & ChrB(Asc(Mid(S,i,1)))
Next
StringToMultiByte = MultiByte
End function
</script>

Related

keep Shell / cmd open when launching R script from VBA

I have an R script that is being run from an Excel workbook via a button that is linked to a VBA script.
The problem is every time the R script encounters an error - say it does not find one of the files it was supposed to read - the Shell / cmd window the R script is running in closes down instantly. The problem with that is you cannot see any clues as to why it failed. I then have to debug it manually by modifying the code and running in RStudio to find the errors - usually I have to do this for other people that do not know R.
The VBA code I use was copied and modified from one of the SO posts I found here. I am not very proficient in VBA and do not understand a lot of the code so I'm looking for a simple solution to this. My VBA code is this:
Option Explicit
Public Sub RunRscript()
ActiveWorkbook.Save
Dim shell As Object
Set shell = VBA.CreateObject("WScript.Shell")
Dim waitTillComplete As Boolean: waitTillComplete = True
Dim style As Integer: style = 1
Dim scriptPath As String
scriptPath = Range("F5").Value
Dim argument As String
argument = Range("F3").Value
Dim path As String
path = """C:\Program Files\R\R-3.4.2\bin\Rscript.exe"" """ & scriptPath & """ """
& argument & """"
ActiveWorkbook.Save
Dim errorcode As Integer
errorcode = shell.Run(path, style, waitTillComplete)
ActiveWorkbook.Save
End Sub
scriptPath points to the path of the R script and argument is an argument I pass to the R script.
I have tried passing the usual arguments to keep the cmd window open but I didn't manage to figure it out. This is also complicated by the fact that as mentioned I do not understand VBA syntax very well and the 'path' variable being very convoluted because of those endless double quotes.
You might use
errorcode = shell.Run("cmd /k " & path, style, waitTillComplete)
instead of
errorcode = shell.Run(path, style, waitTillComplete)
We open a new instance of the command-line tool, thus can use its parameters. The parameter /k keeps the cmd-window open (use /c to close). After the cmd-parameter we add the script to be executed.
But there is one problem: if you close the cmd-window, VBA throws an overflow error. I use a flag in my Excel sheet to switch between debug mode and normal mode:
debugging = Range("N5").Value 'True/False
If debugging Then
errorCode = shell.Run("cmd /k " & path, style, waitTillComplete)
Else
errorCode = shell.Run(path, style, waitTillComplete)
End If
If the script fails I rerun it setting debug mode to True in a cell of the Excel sheet.
Based on this comment:
#FreeMan, the output of the R script is actually a series of Excel workbooks that it opens, prints data in and then saves. it reads a list with the paths of all the files it needs to read as an input to generate the output data required to print in excel. Sometimes, one of the paths in that list is wrong, so the program stops halfway and there is no clue as to why for the user. (the reason could be something else as well). It would be good if I could pass the text that is generated in shell / cmd automatically to a notepad / textpad file at least, so the user could then open and check
It sounds like the best bet may be to have your R script validate the paths/files prior to attempting to do its processing. I'm barely familiar with R, but what I know of it there should be a library somewhere that will allow you to test for the existence of a path and/or a file on that path. If it doesn't exist, the script would simply put an error message in the file it was supposed to create/update indicating that it couldn't find the requested path/file, or it could write that message to an error log that could be opened by your VBA code at the completion of its processing.

How to write some amounts to a File?

I'm doing this program for a class; I have a listbox with 4 choices that are counted each time they're selected,and i'm supposed to write out the results to an out.File so that they can then be retrieved and displayed when asked to.
Here's an image,so you can see what i mean.
Here's the code i got for the file part so far:
'declare a streamwriter variable
Dim outFile As IO.StreamWriter
'open file for output
outFile = IO.File.CreateText("Commercials.txt")
'write to file
For intIndex As Integer = 0 To lstCommercial.Items.Count - 1
outFile.WriteLine(lstCommercial.Items(intIndex))
Next intIndex
'close th efile
outFile.Close()
So my problem is this,i can get everything to work except for it to write the totals to the file,with the result of not displaying. How do i go about doing this? What am i doing wrong in any case?
It depends on what lstCommercial.Items is.
If it is a Collection object, then you can get the index of an item using the following:
outFile.WriteLine(lstCommercial.Items.Item(intIndex))
If it is an array, then instead of using the Count property to find the length, you should rather use GetUpperBound(0) to find the last index:
For intIndex As Integer = 0 To lstCommercial.Items.GetUpperBound(0)
I have very little experience in Visual Basic so I am probably wrong, but I have just gathered this from reading Arrays in Visual Basic and Collection Object (Visual Basic).
Also, looking at the docs here, you may need to 'Flush' the buffer to the file before closing it:
outFile.Flush()
'close the file
outFile.Close()

BizTalk SourceFileName becomes dehydrated

I'm trying to use a custom filename since i need to create two files (a backupfile) so i followed the following tutorial to create filename Here
now when i test this with DELCUS%MessageID%.txt everything works fine but when i change it to DELCUS%SourceFileName%.txt the interface becomes permanently dehydrated.
the only thing i do for the filename is this
fileName = "ContExt" + System.DateTime.Now.ToString();
Message_send_Belspeed_BeautDay_ContExt(FILE.ReceivedFileName) =
fileName;
is there any reason why the use of SourceFileName would cause this to dehydrate?
Found the issue.
after a while the interface did crash and the filename looks like
DELCUS2012 10:50:40.txt
having : in a filename is not good.
This is just a standard windows file naming limitation, you can't name your file using any of these characters "\ / : * ? " < > |". So obviously your instances are going to get stuck!!

Escaping parameters passed to perl script within Windows Shell

I have a perl script that was provided by a vendor, and that takes a series of parameters. I would like to call this via a Windows Shell object in ASP classic.
If I type the following in the cmd line on the web server, it works just fine:
path_to_perl\perl.exe path_to_pl\myfile.pl --arg1 "something" --arg2 "somethingelse"
If I do the following in ASP classic, it doesn't work:
strCMD = "path_to_perl\perl.exe path_to_pl\myfile.pl --arg1 ""something"" --arg2 ""somethingelse"""
Set objWShell = CreateObject("WScript.Shell")
Set objCmd = objWShell.Exec("cmd.exe /c " & strCMD)
The issue is that the argument have all sorts of special characters, so I need to quote them. I have read conflicting information as to how I should escape them - via a caret or a back-slash. Any help would be greatly appreciated!
Shoulf call Perl directly, like this:
system_call_test( 'c:/complete/path_to_pl/myfile.pl --arg1 "something" ... ' )
See the discussion here: How to call perl programs from ASP page
and aspecially the answers of Charles K. Clarkson here.
It will simplify the problem, as you will not have to deal with escaping characters
for ASP, CMD and Perl - all at the same time.
(in that discussion the problem was a syntax-error at the Perl-script, eventually,
but it still shows how to code it in ASP).

How to make a non-blocking pipe from the command-line in Solaris?

I'm trying to write a lua script that reads input from other processes and analyzes it. For this purpose I'm using io.popen and it works as expected in Windows, but on Unix(Solaris) reading from io.popen blocks, so the script just waits there until something comes along instead of returning immediately...
As far as I know I can't change the functionality of io.popen from within the script, and if at all possible I would rather not have to change the C code, because then the script will then need to be bound with the patched binary.
Does that leave me with any command-line solutions?
Ok got no answers so far, but for posterity if someone needs a similar solution I did the following more or less
function my_popen(name,cmd)
local process = {}
process.__proc = assert(io.popen(cmd..">"..name..".tmp", 'r'))
process.__file = assert(io.open(name..".tmp", 'r'))
process.lines = function(self)
return self.__file:lines()
end
process.close = function(self)
self.__proc:close()
self.__file:close()
end
return process
end
proc = my_popen("somename","some command")
while true
--do stuf
for line in proc:lines() do
print(line)
end
--do stuf
end
Your problems seems to be related to buffering. For some reason the pipe is waiting for some data to be read before it allows the opened program to write more to it, and it seems to be less than a line. What you can do is use io.popen(cmd):read"*a" to read everything. This should avoid the buffering problem. Then you can split the returned string in lines with for line in string.gmatch("[^\n]+") do someting_with(line) end.
Your solution consist in dumping the output of the process to a file, and reading that file. You can replace your use or io.popen with io.execute, and discard the return value (just check it's 0).

Resources