I'm trying to figure out a way to open SAS programs in new instances of the Enhanced Editor by default on click.
The question has been asked before but no luck.
This paper describes the way a program is opened with the Enhanced Editor. The full command is :
"C:\PROGRA~1\SASHome\SASFOU~1\9.3\core\sasexe\SASOACT.EXE" action=Open
datatype=SASFile filename="%1" progid=SAS.Application.903
The author explains that:
The sasoact.exe program is used to launch an OLE automation session of SAS.
Automation
is a mechanism through
which one Windows application can control another application programmatically. When you double-click a SAS file
type, sasoact.exe checks to see if an existing OLE automation session of SAS is running. If not, it then invokes an
OLE automation session of SAS. Once there is an active
SAS automation server session, any further calls from
sasoact.exe are handled by the existing SAS session instead of in a new
SAS session.
I guess having only one OLE session is usefull in some way or another but it's really annoying when you have to manually open a new EE instance every time you want to run multiple jobs. Not to mention that sasoact targets the first session initiated and if a job is already running on that session well your program is not going to open.
Is there a way to directly request a new instance of the OLE session or perhaps "trick" sasoact.exe into not seeing the opened sessions ?
[EDIT] Well too bad it's been closed as duplicate because the answer is substantially different than the other question's. Also it might help others who do not want to run their programs from a batch file.
Here is the registry key that works:
"C:\Program Files\SAS\SASFoundation\9.2(32-bit)\sas.exe" -initstmt "dm 'whost;include ''%1'' ';"
I added it in HKEY_CLASSES_ROOT\SAS.Program.701\shell\Open New\command so now I have a neat little extra option in my drop-down menu that effectively opens programs in new sessions on click:
A similar thread showing the use of a batch file to open a SAS program in a new session is available here.
If you want to open a .sas program in a new session by simply clicking the program here is how to do it:
You have to add an entry to the registry. Be careful when messing around with registry files, always back up your entries.
Open the registry editor (WIN+R > regedit).
In the directory HKEY_CLASSES_ROOT\SAS.Program.701\shell\ create a sub-directory with a meaningful name(right-click on shell > New > Key). I named mine "Open New". In this new sub-directory create another sub named command. You should now have a path that looks like:
HKEY_CLASSES_ROOT\SAS.Program.701\shell\Open New\command
In here, right-click on the file on the registry file on the right > Modify and add the following in the Value data field (change the path of sas.exe if needed)
"C:\Program Files\SAS\SASFoundation\9.2(32-bit)\sas.exe" -NOTUTORIALDLG -initstmt "dm 'whost;include ''%1'' ';"
Close the editor. You should now have the new option specified in the drop-down menu of the right-click on a .sas program:
This option will open your program with the Enhanced Editor in a new SAS session.
Now if you want it to work for double-clicking I suppose you'd have to replace the value in the Open sub-directory with the one from above. I haven't done it and I don't recommend it, the extra option in the drop-down is enough for me.
Related
My Log window seems happend some font cahe issue, Sometimes it suddenly makes the font BOLD and that bothered me these days. Here is my first question: Dose anybody has any hints about the font issue?
Forunately I find the Log window return to normal if only I close and reopen it, so here comes my
second question: Is it possible to open and close the Log window in SAS DMS? If so, how to write it?
Use the DM statement to programmatically submit available SAS Commands under Windows or SAS Display Manager Windows Window Commands and most important for this question SAS Windows and Access Methods
The LOG command has a seemingly undocumented (online web docs) option OFF. There is likewise a seemingly undocumented command CLEAR. These commands are documented in Windows DM via F1 (Help) -- do a Quick Search for "SAS Windows and Access Methods".
DM 'CLEAR LOG; LOG OFF' LOG;
You might also want to check the DM windows font setting. Submit or issue DLGFONT
DM `DLGFONT`;
Finally, worst case, there is a possibility the SAS DM configuration file is damaged. Locate regstry.sas7bitm, profile.sas7bcat in the sasuser operating system folder and , when SAS is closed, rename them so they are recreated anew at the next DM SAS session start.
If you are using a different SAS client, update your question and add your system setup.
I'm using System function System(mypath/test.xls) to open and edit an excel sheet in C++ run time. It opens my excel sheet, allows me to edit ans close the same. After closing the excel sheet, the control goes to the code again. Everything works fine unless there is already some other excel sheet opened. If there is some other excel sheet already opened in the machine, I will not able to edit and close so that control goes to code. Can anyone suggest any solutions for this issue.
What is happening is your System(..) function call is asking the Windows shell to find the application associated with your file (test.xls) , which is Excel. Then if Excel is already running it is asked to open file. If the application is not running, then Windows starts the application for you.
So if the application is not already running and it is started for you it becomes associated with your program as a 'child' process. Therefore your System(..) call waits for it to end before continuing. If however Excel is already running then once Windows informs that instance of your desire to open the file test.xls, your call to System(..) returns immediately.
You can avoid this by explicitly running the Excel program by giving the full path to the Excel EXE file. And including the /x command line argument and full path to your file. The /x causes Excel to open a new process and then open your file. This new process is a child of your program's so the System(..) call will wait..
I'm not familiar with the System(..) call (is it like the system(..) one?) you may have to provide the switch /x, and path arguments as distinct arguments to this call rather than in one long string. Also there may be options on how your child process is launched, so waiting for it to return may be optional and so forth.
For example we have a TextEditor Application. Like notepad++. We have tabs at which file content was displaying.
The default text editor in OS is set to TextEditor Application. When we open a new file application added a tab and put content to it.
How to make an application not to run a new instance when opening a new file in Qt?
Which is the best way you think?
The problem is how can you make a single-instance application. When you open a file the operating system will open the associated application and give it the file as a command line argument. You cannot simply delegate an 'open file' command to a running application through OS mechanism, you have to implement it by yourself.
At the AppWhirr project we used QLocalServer/Client to communicate between instances: when the AppWhirr app is executed it checks whether a QLocalServer with a fix ID is already taken or not. If not this instance of the application is the first/only running instance. If the ID is already taken it means another instance of the application is already running so this second instance will only do 2 things: send the given input arguments to the other instance through Qt's local client/server communication, and when it's successfully finish the communication it will quit (the second instance).
That's one solution for the problem, requires quite a bit of coding and I would not recommend it if you don't want to use local client/server communication for anything else, but it's a viable solution.
Another solution would be that the first instance of the application creates a text file at a fixed location and writes our the instance's ID. After this the second instance can read the text file and send a message to the specified ID. And of course the first instance have to remove the text-file when it quits and probably you have to implement some fail-safe code to remove the text-file in case the first instance crashes. This solution will use less resource than the first one but requires a fail-safe cleanup code.
Or as a third option you can use third-party solutions like #Matteo Italia suggested.
I'm trying to fulfill a client request here, and I'm not entirely sure I can actually do it. I have an MFC application that relies upon ShellExecute to open files in their appropriate viewer, which spawns multiple viewers if you try to open multiple files one after the other. If you open one .txt document, and then open another, two copies of notepad appear as expected.
The client wants us to change this functionality - Windows' functionality - to just pass file locations to any viewers that might already be opening. The first image clicked should open Image Viewer, but any other should just be opened in that existing process.
Is that kind of inter-application control/communication possible? Can I generically "pass" files to existing processes? I don't think I can. Executing a program with a file as a parameter is one thing, but passing a file to a running process is something else altogether. I'm not sure you can do that generically, I don't think that kind of functionality is anywhere in the Windows APIs.
I could be wrong, though.
This isn't possible if the viewer don't support multiple open files in same instance.
in your example: notepad will launch a new version with each file, while Notepad++ (a free editor) will open in same instance in a new tab.
The first thing you should try is calling the program again with the new parameters. If the program is written in such a way it will delegate the new parameter to the existing instance. Notepad doesn't do this, image viewer may though.
The next thing you can try is managing the life of the application by keeping track of the handle yourself. You call CreateProcess, so you create and own the handle to this process. On the next call to CreateProcess, enumerate the open windows and try to find your last handle. If the handle is found, close it and continue with your open process. You should only get one open application. For the most reliable solution, put this in a separate thread and wait for the handle (as well as a new request event) to avoid any race conditions.
I have a situation that has been partially covered by other answers at SO, but I cannot find a complete answer. In short, we are trying to use URL's for our specific data types that when double clicked will open up our application and load those data sets into that app. We have this part working.
(for example, an URL might look like this: resource://shaders/basic_shader.hlsl)
What we would like to do is to prevent new instances of the application from opening when a new URL is double clicked. For example, let's say we have a URL that opens up a shader in our shader editor. When clicking this resource URL, it will open our shader editor. When a new shader URL is clicked, we'd like to be able to open up the shader in the currently running application and have it open up the new shader in a new tab in our editor.
We can easily detect if another instance of our application is running. The problem that we don't know how to easily solve is how to tell the currently running application to open up this new file for editing. This behavior is very much like the Apple Finder.
In unix, you could emulate this behavior by having your application open some named pipe and then new apps could check if this pipe is active and then send the document data down the pipe. Is there a more standard windows way of achieving this behavior?
We need a C/C++ solution. Thanks.
Named pipe is the best way.
First instance of your application opens the pipe and listens to it (use PIPE_ACCESS_INBOUND as dwOpenMode and the same code will also allow you to detect running instances).
All subsequent instances check that they are not alone, send command line argument to the pipe and shut down.
Create a named mutex when application launches as David Grant said, then before displaying the UI for the second URL, check for this mutex, if it is already created then just quit by passing the new URL to the first launched application (Have interface in the application to set the URL and tell to redirect programatically)
You can't avoid the program associated with the url to be executed.
The "windows" solutions would be to send a message (via DDE in the old days but maybe there is something more "modern" now) to the previously running application with the url then quit ...
You can acquire a named mutex upon startup and enforce it that way.
http://www.google.com/search?hl=en&q=named+mutex+single+instance
CreateMutex on MSDN
I got this working pretty well for my C++ MFC application by following Joseph Newcomer's tutorial here. He uses a named mutex that is checked on startup and a message sent to the already-running application with the new resource to be opened.