Closed romancitodev closed 1 year ago
This does not sound like an issue with windows-service
, but rather with dirs
, right? As the service is ran by the system user account it might not have any desktop folder. You can't expect it to find your user's desktop folder since the program is not running as your user.
So, how can i configure the service to run with my user?
I tried using this
use std::ffi::OsString;
use windows_service::{
service::{ServiceAccess, ServiceErrorControl, ServiceInfo, ServiceStartType, ServiceType},
service_manager::{ServiceManager, ServiceManagerAccess},
};
const SERVICE_NAME: &str = "SpeedOS";
fn main() -> windows_service::Result<()> {
let service_manager =
ServiceManager::local_computer(None::<&str>, ServiceManagerAccess::all())?;
let service_binary_path = std::env::current_exe()
.unwrap()
.with_file_name("service.exe");
println!("{service_binary_path:?}");
let service_info = ServiceInfo {
name: OsString::from(SERVICE_NAME),
display_name: OsString::from(SERVICE_NAME),
service_type: ServiceType::USER_OWN_PROCESS | ServiceType::INTERACTIVE_PROCESS,
start_type: ServiceStartType::OnDemand,
error_control: ServiceErrorControl::Normal,
executable_path: service_binary_path,
launch_arguments: vec![],
dependencies: vec![],
account_name: Some(".\\Shyrux".into()), // run as System
account_password: Some("password".into()),
};
let service = service_manager.create_service(&service_info, ServiceAccess::all())?;
service.set_description("Service to just write a file idk")?;
println!("{SERVICE_NAME} installed correctly.");
Ok(())
}
But when I install it, the service is marked as USER_OWN_PROCESS TEMPLATE
and WIN32
returns 1077
Error code.
@ChirujanoCodding Your code above should create a template for a per-user service, but you might need to log out and log in again for the actual service to be created for your user:
Per-user services are services that are created when a user signs into Windows or Windows Server and are stopped and deleted when that user signs out.
https://learn.microsoft.com/en-us/windows/application-management/per-user-services-in-windows
This creates an instance of that service for every logged in user.
You probably don't have to specify account_name
, account_password
, or INTERACTIVE_PROCESS
for a per-user service template. If you don't want to create a per-user service, you probably want to use your account instead of creating the template (and not use USER_OWN_PROCESS
).
@dlon Hi, thanks for the answer but i still don't get it how i did to create a template, i just replaced ServiceType::OWN_PROCESS
for ServiceType::USER_OWN_PROCESS
.
The reason why i'm using USER_OWN_PROCESS
is because i need access to the user desktop to create a file, so i don't even know if i need the account_name
& account_password
but sounds logic to me.
Tl;dr: Use USER_OWN_PROCESS
if you want a separate instance of the service for each user, created at login and destroyed on logout. Use account_name
/account_password
if you want a single service logged in as that particular user. I've tried each and dirs_next::desktop_dir()
returns the correct path in each case.
Here's an example using USER_OWN_PROCESS
. I didn't bother to set the service status, but you get the idea:
use std::ffi::OsString;
use windows_service::{
service::{ServiceAccess, ServiceErrorControl, ServiceInfo, ServiceStartType, ServiceType},
service_manager::{ServiceManager, ServiceManagerAccess},
};
const SERVICE_NAME: &str = "Test service";
fn main() -> windows_service::Result<()> {
let mut args = std::env::args();
args.next();
let arg = args.next();
if arg.as_ref().map(|s| s.as_str()) == Some("--run-as-service") {
if let Some(dir) = dirs_next::desktop_dir() {
std::fs::write(dir.join("testlog.txt"), "Hello world");
}
return Ok(());
}
let service_manager =
ServiceManager::local_computer(None::<&str>, ServiceManagerAccess::CREATE_SERVICE)?;
let service_binary_path = std::env::current_exe().unwrap();
println!("{service_binary_path:?}");
let service_info = ServiceInfo {
name: OsString::from(SERVICE_NAME),
display_name: OsString::from(SERVICE_NAME),
service_type: ServiceType::USER_OWN_PROCESS,
start_type: ServiceStartType::AutoStart,
error_control: ServiceErrorControl::Normal,
executable_path: service_binary_path,
launch_arguments: vec![OsString::from("--run-as-service")],
dependencies: vec![],
account_name: None,
account_password: None,
};
let service = service_manager.create_service(&service_info, ServiceAccess::all())?;
service.set_description("Test service")?;
println!("{SERVICE_NAME} installed correctly.");
Ok(())
}
I had to log out and log in again for the service to become visible, and the user-specific service gets assigned a suffix.
I also tried using ServiceType::OWN_PROCESS
as the service_type
flag and setting the account with account_name
and account_password
. This worked too. You can also change the account later in the service console (services.msc
).
@dlon Thanks you! finally i used the USER_OWN_PROCESS
and i logged out and logged in and worked!
I'm making a service that only write a
.log
in the desktop but the program is not working. I tried usingdirs
but nothing works. the service crashes with a1067
error.If i do this:
the program crashes, but If i do this:
The program works. But i need to find dinamically the desktop.