How to retain service settings through InstallShield upgrade install - windows-services

I have an InstallScript project in IS2010. It has a handful of services that get installed. Some are C++ exes and use the "InstallShield Object for NT Services". Others are Java apps installed as services with Java Service Wrapper through LaunchAppAndWait command line calls. Tomcat is also being installed as a service through a call to its service.bat.
When the installer runs in upgrade mode, the services are reinstalled, and the settings (auto vs. manual startup, restart on fail, log-on account, etc.) are reverted to the defaults.
I would like to save the service settings before the file transfer and then repopulate them afterward, but I haven't been able to find a good mechanism to do this. How can I save and restore the service settings?

I got this working by reading the service information from the registry in OnUpdateUIBefore, storing it in a global variable, and writing the information back to the registry in OnUpdateUIAfter.
Code:
export prototype void LoadServiceSettings();
function void LoadServiceSettings()
number i, nResult;
string sServiceNameArray(11), sRegKey, sTemp;
BOOL bEntryFound;
begin
PopulateServiceNameList(sServiceNameArray);
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
//write service start values to the registry
for i = 0 to 10
if (ServiceExistsService(sServiceNameArray(i))) then
sRegKey = "SYSTEM\\CurrentControlSet\\Services\\" + sServiceNameArray(i);
nResult = RegDBSetKeyValueEx(sRegKey, "Start", REGDB_NUMBER, sServiceSettings(i), -1);
if(nResult < 0) then
MessageBox ("Unable to save service settings: " + sServiceNameArray(i) + ".", SEVERE);
endif;
endif;
endfor;
RegDBSetDefaultRoot(HKEY_CLASSES_ROOT); //set back to default
end;
export prototype void SaveServiceSettings();
function void SaveServiceSettings()
number i, nType, nSize, nResult;
string sServiceNameArray(11), sRegKey, sKeyValue;
begin
PopulateServiceNameList(sServiceNameArray);
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
for i = 0 to 10
if (ServiceExistsService(sServiceNameArray(i))) then
//get service start values from registry
sRegKey = "SYSTEM\\CurrentControlSet\\Services\\" + sServiceNameArray(i);
nResult = RegDBGetKeyValueEx(sRegKey, "Start", nType, sKeyValue, nSize);
if(nResult < 0) then
MessageBox ("Unable to save service settings: " + sServiceNameArray(i) + ".", SEVERE);
endif;
sServiceSettings(i) = sKeyValue;
endif;
endfor;
RegDBSetDefaultRoot(HKEY_CLASSES_ROOT); //set back to default
end;

Related

Is it possible to upload file on server using scheduler or windows service?

I am trying to do file upload using quartz job scheduler. but, it is not working.
Is it possible to upload file to the server using job or windows sevice.
I have googled but not understand much. please provide some link for reference.
It is possible to upload file using windows service i guess. We build a similar kind of windows service for inserting to database recursively.[1]: https://www.c-sharpcorner.com/article/create-windows-services-in-c-sharp/
protected override void OnStart(string[] args)
{
WriteToFile("Service is started at " + DateTime.Now);
Fileupload();
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 1000*60*60*10; //number in milisecinds
//timer.Interval = 1000 * 60;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
Fileupload();
WriteToFile("Service is recall at " + DateTime.Now);
}
//you can use the above 2 functions in Serivce Cs file and you define your Custom Fileupload Function for uploading file. Hope this works for you

Using Redis as a Link Between Docker Containers

I have a docker-compose file with several containers in, two of which are supposed to communicate via a Redis DB. Both containers have connections to Reids and I can read/write from both. However I'd like a container to be triggered every time the something is added from the other container. I thought I could accomplish this via Redis Sub/Pub but it when I run the code it never triggers anything, even when I can see I've added new items to the Redis queue.
From this I have two questions:
1. Is what I'm looking to do even possible? Can I do publish/subscribe in in two separate docker containers and expect it work as described above?
2. If it is possible, can someone please point me below where I"m going wrong with this tools?
This is my function that I add new data to the Redis queue and then publish the data in Docker container 1.
func redisShare(key string, value string) {
jobsQueue.Set(key, value, 0) //setting in the queue
jobsQueue.Publish(key, value) //publishing for the other docker container to notice
fmt.Println("added ", key, "with a value of ", value, "to the redis queue")
}
I'm using this line in my other docker container to subscribe to the Redis queue and listen for changes:
redisdb.Subscribe()
I would expect if something was added to the redis queue it would share the data to the other container and I'd see the message received, but right now Docker Container 2 just runs and then closes.
Thanks!
Just in case anyone else wonders about the answer: I ended up using a combination of both Aleksandrs and sui's answers.
In my first Docker container I published the results to a specific channel:
publishData := redisdb.Subscribe("CHANNELNAME")
And then in my second Docker container that was subscribing to the channel, thanks to sui for the assistance on this part, I subscribed to the channel and pulled the both the UID and the IP information like so:
ch := pubsub.Channel()
for msg := range ch {
fmt.Println(msg.Payload)
s := strings.Split(msg.Payload, ":")
UID, IP := s[0], s[1]
fmt.Println(UID, IP)
}
This is working great for me so far - thanks so much to sui and Aleksandrs for the assistance!
As from docs
receiver.go
package main
import (
"fmt"
"github.com/go-redis/redis"
)
func main() {
c := redis.NewClient(&redis.Options{
Addr: ":6379",
})
pubsub := c.Subscribe("mychannel1")
// Wait for confirmation that subscription is created before publishing anything.
_, err := pubsub.Receive()
if err != nil {
panic(err)
}
// Go channel which receives messages.
ch := pubsub.Channel()
// Consume messages.
for msg := range ch {
fmt.Println(msg.Channel, msg.Payload)
}
}
sender.go
package main
import (
"time"
"github.com/go-redis/redis"
)
func main() {
c := redis.NewClient(&redis.Options{
Addr: ":6379",
})
// Publish a message.
for range time.Tick(time.Second) {
err := c.Publish("mychannel1", "hello").Err()
if err != nil {
panic(err)
}
}
}

Open external file with Electron

I have a running Electron app and is working great so far. For context, I need to run/open a external file which is a Go-lang binary that will do some background tasks.
Basically it will act as a backend and exposing an API that the Electron app will consume.
So far this is what i get into:
I tried to open the file with the "node way" using child_process but i have fail opening the a sample txt file probably due to path issues.
The Electron API expose a open-file event but it lacks of documentation/example and i don't know if it could be useful.
That's it.
How i open an external file in Electron ?
There are a couple api's you may want to study up on and see which helps you.
fs
The fs module allows you to open files for reading and writing directly.
var fs = require('fs');
fs.readFile(p, 'utf8', function (err, data) {
if (err) return console.log(err);
// data is the contents of the text file we just read
});
path
The path module allows you to build and parse paths in a platform agnostic way.
var path = require('path');
var p = path.join(__dirname, '..', 'game.config');
shell
The shell api is an electron only api that you can use to shell execute a file at a given path, which will use the OS default application to open the file.
const {shell} = require('electron');
// Open a local file in the default app
shell.openItem('c:\\example.txt');
// Open a URL in the default way
shell.openExternal('https://github.com');
child_process
Assuming that your golang binary is an executable then you would use child_process.spawn to call it and communicate with it. This is a node api.
var path = require('path');
var spawn = require('child_process').spawn;
var child = spawn(path.join(__dirname, '..', 'mygoap.exe'), ['game.config', '--debug']);
// attach events, etc.
addon
If your golang binary isn't an executable then you will need to make a native addon wrapper.
Maybe you are looking for this ?
dialog.showOpenDialog refer to: https://www.electronjs.org/docs/api/dialog
If using electron#13.1.0, you can do like this:
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
dialog.showOpenDialog(function(file_paths){
console.info(file_paths) // => this gives the absolute path of selected files.
})
when the above code is triggered, you can see an "open file dialog" like this (diffrent view style for win/mac/linux)
Electron allows the use of nodejs packages.
In other words, import node packages as if you were in node, e.g.:
var fs = require('fs');
To run the golang binary, you can make use of the child_process module. The documentation is thorough.
Edit: You have to solve the path differences. The open-file event is a client-side event, triggered by the window. Not what you want here.
I was also totally struggling with this issue, and almost seven years later the documentation is quite not clear what's the case with Linux.
So, on Linux it falls under Windows treatment in this regard, which means you have to look into process.argv global in the main processor, the first value in the array is the path that fired the app. The second argument, if one exist, is holding the path that requested the app to be opened. For example, here is the output for my test case:
Array(2)
0: "/opt/Blueprint/b-test"
1: "/home/husayngonzalez/2022-01-20.md"
length: 2
So, when you're creating a new window, you check for the length of process.argv and then if it was more than 1, i.e. = 2 it means you have a path that requested to be opened with your app.
Assuming you got your application packaged with the ability to process those files, and also you set the operating system to request your application to open those.
I know this doesn't exactly meet your specification, but it does cleanly separate your golang binary and Electron application.
The way I have done it is to expose the golang binary as a web service. Like this
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
//TODO: put your call here instead of the Fprintf
fmt.Fprintf(w, "HI there from Go Web Svc. %s", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/api/someMethod", handler)
http.ListenAndServe(":8080", nil)
}
Then from Electron just make ajax calls to the web service with a javascript function. Like this (you could use jQuery, but I find this pure js works fine)
function get(url, responseType) {
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = responseType;
request.onload = function() {
if (request.status == 200) {
resolve(request.response);
} else {
reject(Error(request.statusText));
}
};
request.onerror = function() {
reject(Error("Network Error"));
};
request.send();
});
With that method you could do something like
get('localhost/api/somemethod', 'text')
.then(function(x){
console.log(x);
}

Open exe as service without "Interactive Service Detection" message in window 7

I have a simple application that watches a folder for any changes as following:
private void Form1_Load(object sender, EventArgs e)
> {
> FileSystemWatcher w = new FileSystemWatcher();
> w.Path = #"C:\temp";
> w.Changed += new FileSystemEventHandler(OnChanged);
> w.Created += new FileSystemEventHandler(OnChanged);
> w.Deleted += new FileSystemEventHandler(OnChanged);
> w.Renamed += new RenamedEventHandler(OnChanged);
> // Begin watching.
> w.EnableRaisingEvents = true;
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is changed, created, or deleted.
MessageBox.Show("File: " + e.FullPath + " " + e.ChangeType + Path.GetFileName(e.FullPath));
}
I added the same as service from the command prompt as
sc create <service name> binPath= <path of the exe file>
This added the exe in the services and also made the entries in Registry. But when I tried to start the service as
sc start <service name>
it showed up the "Interactive Service Detection" message.
I want to avoid this message from popping up and start the service.
I also need this to be done in c# but if anyone has any idea about doing it in cmd I can add it as a batch file and execute the same.
EDIT I
As #Seva suggested I created a service that calls the exe that I wish. I wrote the following code to start the exe on start of the service:
protected override void OnStart(string[] args)
{
base.OnStart(args);
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
p.StartInfo.CreateNoWindow = false;
p.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
p.StartInfo.WorkingDirectory = #"<my exe path>";
p.StartInfo.FileName = "<myexe.exe>";
p.StartInfo.Arguments = #"<my exe path>";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
p.WaitForExit();
base.Stop();
}
I installed the service successfully but is not starting the exe on starting.
EDIT II
The exe started. The service's property had to be configured to allow service interaction with desktop, but then again the "Interactive service detection" message is coming up.
You will have to rearchitecture your windows service into two parts -- a GUI-less service process and a separate UI app that runs on user desktop. There are many ways service can communicate with UI app. These SO questions will get you started:
GUI and windows service communication
Communication between windows service and desktop app
There is no other way around. BTW, your existing approach is already broken -- for Non-admin users and for remote desktop sessions -- they won't see UI from a service even if they want to.

Run a process on ASP.NET MVC

I'm new on MVC!
I want to run a process on my web app (not for bad purpose), this process can do something, for example it can write a text to a file .txt!
On my local PC, it work well but when I publish it on to host provider, it not work!
How I can do this?
This is my code:
string path = HttpContext.Current.Server.MapPath("~/App_Data/ModuleMaple/ModuleMaple.exe");
Process myproc = new Process();
myproc.StartInfo.FileName = path;
myproc.StartInfo.Arguments ="some argument"
myproc.StartInfo.UseShellExecute = false;
myproc.Start();
myproc.WaitForExit();

Resources