SAS: getting the filesize of created DBF file - stored-procedures

I have SAS stored process that ceates DBF file from SAS data set rr_udf_value and finds its size (F_SIZE):
filename dbfout "/SASInside/DBF/myfile";
proc export
data=rr_udf_value
outfile=dbfout
dbms=dbf
replace;
run;
%let f_nm=/SASInside/DBF/myfile.DBF;
%let rc=%sysfunc(filename(onefile, &f_nm.));
%let fid=%sysfunc(fopen(&onefile));
%let F_SIZE=%sysfunc(finfo(&fid,File Size (bytes)));
%put &F_SIZE;
The problem is that the variable F_SIZE is empty in STP log. But if after execution of STP I run commands
%let f_nm=/SASInside/DBF/myfile.DBF;
%let rc=%sysfunc(filename(onefile, &f_nm.));
%let fid=%sysfunc(fopen(&onefile));
%let F_SIZE=%sysfunc(finfo(&fid,File Size (bytes)));
%put FSIZE=&F_SIZE;
manually, everithing is OK: F_SIZE=17342.
Why F_SIZE is not initialized while running STP, and how could I fix it?
Thanks in advance!

filename() is restricted in environments with OPTION NOXCMD, which is by default set for server environments. This is for security reasons (as XCMD allows shell access). You can enable this with by enabling OPTION XCMD, though your server admin (if this is not you) would have to enable it on the server and not in your local session typically.
See the SAS documentation on XCMD for more information.

Related

Modify Environment Variable Path for local machine with nsis

I'm trying to edit the Local Machine Environment Variable Path with an NSIS script. I've found this interesting post but I haven't been able to "install", if I may say, the alternative build of NSIS they've been talking about in the first answer.
I did try things like this post but without success.
BUT I've managed to use the script from Anders's answer on the same question asked here
The thing is, it only modify the Path Environment table for the current user, and I want to modify it for the local machine.
I've tried to modify the variable here :
Push ${HKEY_CURRENT_USER}
to :
Push ${HKEY_LOCAL_MACHINE}
but it seems to be not enough because I keep getting an error 87.
So my questions are: Is it possible from Anders's script to modify Environment Variable for the Local Machine ? And if yes, how ?
Best regards, Antoine.
The key used by HKLM is also different but once you give it the correct key it works for me:
!include LogicLib.nsh
!include WinCore.nsh
!ifndef NSIS_CHAR_SIZE
!define NSIS_CHAR_SIZE 1
!endif
!ifndef HKEY_LOCAL_MACHINE
!error HKEY_LOCAL_MACHINE
!endif
Function RegAppendString
TODO: Function from https://stackoverflow.com/a/31342128/3501# goes here
FunctionEnd
RequestExecutionLevel Admin ; Request UAC elevation
Section
Push ${HKEY_LOCAL_MACHINE}
Push "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Push "Path"
Push ";"
Push "c:\whatever"
Call RegAppendString
Pop $0
DetailPrint RegAppendString:Error=$0
SectionEnd
but things have moved on since that function was posted and there is now a plug-in specifically created for environment variable manipulation. I would recommend that you try the EnVar plug-in.

GDB 'Addresses'. What are they?

This should be a very simple,very quick qustion. These are the first 3 lines of a program in C I wrote:
Dump of assembler code for function main:
0x0804844d <+0>: push ebp
0x0804844e <+1>: mov ebp,esp
0x08048450 <+3>: and esp,0xfffffff0
... ... ... ... ... ... ...
What is 0x0804844d and 0x0804844e and 0x08048450? It is not affected by ASLR. Is it still a memory address, or a relative point to the file?
If you look at the Intel Developer Manual instruction-set reference you can see that 0x0804846d <+32>: eb 15 jmp 0x8048484 encodes a relative address. i.e. it's the jmp rel8 short encoding. This works even in position-independent code, i.e. code which can run when mapped / loaded at any address.
ASLR means that the address of the stack (and optionally code+data) in the executable can change every time you load the file into memory. Obviously, once the program is loaded, the addresses won't change anymore, until it is loaded again. So if you know the address at runtime, you can target it, but you can't write an exploit assuming a fixed address.
GDB is showing you addresses of code in the virtual-memory space of your process, after any ASLR. (BTW, GDB disables ASLR by default: set disable-randomization on|off to toggle.)
For executables, it's common that only the stack pointer is ASLRed, while the code is position-dependent and loaded at a fixed address, so code and static data addresses are link-time constants, so code like push OFFSET .LC0 / call puts can work, hard-coding the address of the string constant into a push imm32.
Libraries usually need to be position-independent anyway, so ASLR can load them at a randomized address.
But ASLR for executables is possible and becoming more common, either by making position-independent executables (Linux), or by having the OS fix-up every hard-coded address when it loads the executable at a different address than it was compiled for (Windows).
Addresses only have a 1:1 relation to the position within the file only in a relative sense within the same segment. i.e. the next byte of code is the next byte of the file. The headers of the executable describe which regions of the file are what (and where they should be mapped by the OS's program loader).
The meaning of the addresses shown differs in three cases:
For executable files
For DLLs (Windows) or shared objects (.so, Linux and Un*x-like)
For object files
For executables:
Executable files typically cannot be loaded to any address in memory. In Windows there is the possibility to add a "relocation table" to an executable file (required for very old Windows versions); if this is not present (typically the case when using GCC) then it is not possible to load the file to another memory location. In Linux it is never possible to load the executable to another location.
You may try something like this:
static int a;
printf("%X\n", &a);
When you execute the program 100 times you see that the address of a is always the same so no ASLR is done for the executable file itself.
The addresses dumped by objdump are absolute addresses.
For DLLs / .so files:
The addresses are relative to the base address of the DLL (under Linux) or they are absolute addresses (under Windows) that will change when the DLL is loaded into another memory area.
For object files:
When dumping an object file the addresses are relative to the currently displayed section. If there are multiple ".text" sections in a file the addresses will start at 0 for each section.

copy MSSQL server database using ADO and delphi

I need to integrate a few lines of code into my application , which allow me to copy a database from one MSSQL server to another MSSQL server, the code header should be like this
procedure MoveDataBase (OldServername : String; newServerName : String ; Databasename : String);
begin
end;
Any short code and fast working Idea ?
Copy a Database using MS Explorer is no option
The easiest (and maybe also the dumbest) way of transfering a database from one server to the other is to:
1. detach the database on the source server using sp_detach_db
2. copy the physical MDF file to the destination server. You may copy the LDF as well, but imho it is not necessary.
3. attach the database on the destination server using sp_attach_db
You might also replace #1 and #3 by a BACKUP/RESTORE as stated earlier. In any case (I am repeating the commments), you'd need a bit more than just server name and database, i.e. login credentials, for example.

using cmd to create .txt containing url based on ipconfig and modem-required info

I'm not too familiar with cmd or anything, but I have done some research and put together a bit of what I want. This .bat I'm trying to make would take the output of ipconfig/all and select the mac address and ip address of the ethernet adapter and insert them in key locations in a pre-prescribed url for those instances when a computer doesn't automatically redirect to the front page of my hotel's internet billing setup. this is not official work; I am only trying to "ease my burden" a bit and save time typing.
the full address I need to create in a .txt is 000.000.000.00/defaulta.php?mac=xxxxxxxxxxxx&ip=xxx.xxx.xx.xxx
everything but the mac and ip address (both listed as x's) are exactly as they need to be in every case. the ip address shown censored with 0's is intentionally changed for security reasons, and no work needs to be done for that. I have been able to create a simple .bat to create an output of the ipconfig data onto any user's desktop for easy access:
#echo off
ipconfig/all > %userprofile%\Desktop\url_address.txt
I have tried using other parsing solutions to get the data that I need, but the one easiest for me to adapt (linked here) would only output the last instance, not the first or any in between when I make the simplest substitution. I could try to use one of the solutions for only selecting certain lines, but I've seen some computers listing their ethernet first and wireless second, while others list wireless first and ethernet second. I need to parse based specifically on the ethernet lines, as wireless internet is not available in the rooms.
here's an example of the output from my personal pc:
Ethernet adapter Local Area Connection:
Connection-specific DNS Suffix . : xxxx.net
Description . . . . . . . . . . . : Atheros AR8121/AR8113/AR8114 PCI-E Ethernet Controller
Physical Address. . . . . . . . . : xx-xx-xx-xx-xx-xx
DHCP Enabled. . . . . . . . . . . : Yes
Autoconfiguration Enabled . . . . : Yes
Link-local IPv6 Address . . . . . : xxxx::xxxx:xxxx:xxxx:xxxx%12(Preferred)
IPv4 Address. . . . . . . . . . . : xxx.xxx.xx.xxx(Preferred)
anyone who looks up their own and compares will see it's not all the same length, so parsing based on length of characters won't work as different guests will have different cards, etc. this means I need to parse two specific points, the physical address for the mac in the url and the ipv4 address for the ip address in the url. would this mean I have to make two texts, one for each parsing? and how will these two variables be able to be inserted into the final url?
so my main questions are:
1) is it possible to take the two parts I need from the ethernet data and insert them into the appropriate places in the required link and put it in a .txt, and if so, what exactly needs to be done?
2) does the full function I intend need to be done through several .txt files being written as the function progresses to the final solution, or can this all be output to one text file on the guest's desktop for less clutter and easier deletion?
Question was tl;dr. Does this do what you're looking for? Modify xxxx.net and 000.000.000.00 as appropriate.
#echo off
setlocal enabledelayedexpansion
set found=0
for /f "tokens=1,2 delims=:(" %%I in ('ipconfig /all') do (
if !found!==1 (
for /f %%x in ('echo "%%I" ^| find "Physical Address"') do set mac=%%J
for /f %%x in ('echo "%%I" ^| findstr "IP[v4]*.Address"') do (
set ip=%%J
goto next
)
)
for /f %%x in ('echo "%%J" ^| find /i "xxxx.net"') do set found=1
)
echo Couldn't scrape info. Press any key to exit.
pause >NUL
goto :EOF
:next
set mac=%mac: =%
start http://000.000.000.00/defaulta.php?mac=%mac:-=%^&ip=%ip: =%
It performs an ipconfig /all and loops through the output, ignoring everything until it encounters xxxx.net (your connection-specific DNS suffix). Then it looks for Physical Address and IPv4 address from there. Spaces have to be removed from both captures, and dashes removed from the MAC address, all through variable string substitution. Then it launches the user's default web browser to visit the URL you built.
If you actually do need this URL written to a text file instead of launched, then change
start http://000.000.000.00/defaulta.php?mac=%mac:-=%^&ip=%ip: =%
to
echo http://000.000.000.00/defaulta.php?mac=%mac:-=%^&ip=%ip: =% >outfile.txt
Be sure to put a space before the > to make sure Windows redirects stdout to the text file rather than whatever number the IP address happens to end with.
UPDATE 2013.02.27:
The above stuff should work regardless of user access level (administrator or normal user). If you want to simulate running as a non-privileged user, run the following command:
runas /trustlevel:0x20000 cmd
... to open a cmd prompt with restricted privileges. Then you can see for yourself that ipconfig /all still works.
For what it's worth, ipconfig /all is not the only place to scrape the IP and MAC address. If you'd like an alternative to the above script, try this one:
#echo off
setlocal
for /f "tokens=1,2 delims=={}," %%I in (
'wmic nicconfig where ^(ipenabled^='TRUE' and dnsdomain is not null^) get ipaddress^, macaddress /format:list'
) do (
if %%I==IPAddress set ip=%%~J
if %%I==MACAddress set mac=%%J
)
start "" "http://000.000.000.00/defaulta.php?mac=%mac::=%&ip=%ip%"
As before, don't forget to change the IP address in the URL as appropriate.
Update 2013.03.29:
Well, since nothing else has worked for every client computer (as wmic will not work on WinXP Home), and just to see whether I could more than anything, here's another one to try -- a batch / JScript hybrid script. Save this with a .bat extension and I think it should work on every version of Windows after 98 and ME (Mistake Edition, if I recall correctly).
As before, don't forget to replace 000.000.000.00 in the url.
#if (#a==#b) #end /* <-- ignore this, please
:: batch portion
#echo off
setlocal
for /f "tokens=1,2" %%I in ('cscript /nologo /e:jscript "%~f0"') do (
set mac=%%I
set ip=%%J
)
start "" "http://000.000.000.00/defaulta.php?mac=%mac::=%&ip=%ip%"
goto :EOF
:: JScript portion (leave this weird bit here, please) --> */
var wmi = GetObject("winmgmts:\\\\.\\root\\cimv2");
var adapters = wmi.InstancesOf("Win32_NetworkAdapterConfiguration");
for (var res=new Enumerator(adapters); !res.atEnd(); res.moveNext()) {
var adapter = res.item();
/* -------------------------------------------------------------
Note to supergaijin: If this script fails like all the others,
try removing "|| !adapter.DNSDomain" from the following line so
it reads as follows: if (!adapter.IPEnabled) continue;
------------------------------------------------------------- */
if (!adapter.IPEnabled || !adapter.DNSDomain) continue;
WSH.Echo(adapter.MACAddress + ' ' + adapter.IPAddress.toArray()[0]);
}
Credits: I stumbled upon the Win32_NetworkAdapterConfiguration class using WMI Explorer. I figured out how to query its child instances with the help of Scriptomatic (which was much more useful than the TechNet documentation).

How to get Excel version and macro security level

Microsoft has recently broken our longtime (and officially recommended by them) code to read the version of Excel and its current omacro security level.
What used to work:
// Get the program associated with workbooks, e.g. "C:\Program Files\...\Excel.exe"
SHELLAPI.FindExecutable( 'OurWorkbook.xls', ...)
// Get the version of the .exe (from it's Properties...)
WINDOWS.GetFileVersionInfo()
// Use the version number to access the registry to determine the security level
// '...\software\microsoft\Office\' + VersionNumber + '.0\Excel\Security'
(I was always amused that the security level was for years in an insecure registry entry...)
In Office 2010, .xls files are now associated with "“Microsoft Application Virtualization DDE Launcher," or sftdde.exe. The version number of this exe is obviously not the version of Excel.
My question:
Other than actually launching Excel and querying it for version and security level (using OLE CreateOLEObject('Excel.Application')), is there a cleaner, faster, or more reliable way to do this that would work with all versions starting with Excel 2003?
Use
function GetExcelPath: string;
begin
result := '';
with TRegistry.Create do
try
RootKey := HKEY_LOCAL_MACHINE;
if OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\excel.exe', false) then
result := ReadString('Path') + 'excel.exe';
finally
Free;
end;
end;
to get the full file name of the excel.exe file. Then use GetFileVersionInfo as usual.
As far as I know, this approach will always work.
using OLE CreateOLEObject('Excel.Application'))
you can get installed Excel versions by using the same registry place, that this function uses.
Basically you have to clone a large part of that function registry code.
You can spy on that function call by tools like Microsoft Process Monitor too see exactly how does Windows look for installed Excel - and then to do it exactly the same way.
You have to open registry at HKEY_CLASSES_ROOT\ and enumerate all the branches, whose name starts with "Excel.Application."
For example at this my workstation I only have Excel 2013 installed, and that corresponds to HKEY_CLASSES_ROOT\Excel.Application.15
But on my another workstation I have Excel 2003 and Excel 2010 installed, testing different XLSX implementations in those two, so I have two registry keys.
HKEY_CLASSES_ROOT\Excel.Application.12
HKEY_CLASSES_ROOT\Excel.Application.14
So, you have to enumerate all those branches with that name, dot, and number.
Note: the key HKEY_CLASSES_ROOT\Excel.Application\CurVer would have name of "default" Excel, but what "default" means is ambiguous when several Excels are installed. You may take that default value, if you do not care, or you may decide upon your own idea what to choose, like if you want the maximum Excel version or minimum or something.
Then when for every specific excel branch you should read the default key of its CLSID sub-branch.
Like HKEY_CLASSES_ROOT\Excel.Application.15\CLSID has nil-named key equal to
{00024500-0000-0000-C000-000000000046} - fetch that index to string variable.
Then do a second search - go into a branch named like HKEY_CLASSES_ROOT\CLSID\{00024500-0000-0000-C000-000000000046}\LocalServer ( use the fetched index )
If that branch exists - fetch the nil-named "default key" value to get something like C:\PROGRA~1\MICROS~1\Office15\EXCEL.EXE /automation
The last result is the command line. It starts with a filename (non-quoted in this example, but may be in-quotes) and is followed by optional command line.
You do not need command line, so you have to extract initial commanlind, quoted or not.
Then you have to check if such an exe file exists. If it does - you may launch it, if not - check the registry for other Excel versions.

Resources