system_extensions/
lib.rs

1/**
2    System Extensions
3    -----------------
4    System Extensions is a cross-platform library full of useful operating system functionalities.
5    The goal with System Extensions is to provide an easy to use and powerful library to support
6    all 3 of the major operating systems.
7*/
8/*
9    Externing used crates.
10 */
11#[macro_use]
12extern crate bitflags;
13
14/*
15
16    Windows Specific Crates.
17
18 */
19#[cfg(windows)]
20extern crate winapi;
21
22#[cfg(windows)]
23extern crate windows;
24
25#[cfg(windows)]
26pub(crate) mod bindings{
27    ::windows::include_bindings!();
28}
29
30/*
31    Mac Specific Crates
32 */
33#[cfg(target_os = "macos")]
34#[macro_use]
35extern crate objc;
36
37#[cfg(target_os = "macos")]
38extern crate cocoa;
39
40/*
41
42    The modules of System Extensions.
43
44 */
45
46/**
47    The core of system_extensions.
48*/
49#[doc(hidden)]
50pub mod core;
51
52/**
53    The internal code for system_extensions.
54*/
55#[doc(hidden)]
56pub mod internal;
57
58/**
59    Feature that involves system processes.
60*/
61pub mod processes;
62/**
63    Feature that involves additional file metadata editing.
64*/
65pub mod metadata;
66/**
67    Experimental Feature that allows the creation of GUI dialogues.
68*/
69pub mod dialogues;
70
71/**
72    Experimental feature that allows the for the creation of notifications on the Operating System.
73*/
74pub mod notifications;
75
76/**
77   If an error occurs in the Windows API, you can check it here.
78
79   Note: This is for debugging only. Do not call this method in production code.
80
81   [View the error codes here.](https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes)
82*/
83#[cfg(windows)]
84pub fn obtain_error() -> u32 {
85    use winapi::um::errhandlingapi::GetLastError;
86    unsafe {
87        return GetLastError();
88    }
89}
90/*
91
92    Windows tests.
93
94 */
95#[cfg(test)]
96#[cfg(windows)]
97mod tests {
98    use std::fs::File;
99    use std::ops::Add;
100    use std::path::{Path, PathBuf};
101
102    use crate::metadata::time::{FileTime, set_creation_date};
103    use crate::metadata::attribute::{set_attribute, Attributes, has_attribute, get_attributes};
104    use crate::processes::processes::find_process_id;
105    use crate::dialogues::filebox::{Filter};
106    use crate::obtain_error;
107    use crate::dialogues::messagebox::{MessageBox, WindowType, IconType};
108    use crate::dialogues::filebox::FileBox;
109    use crate::notifications::notification::SimpleNotification;
110
111    #[test]
112    fn it_works() {
113        // let val = find_process_id("Discord.exe").expect("An error occurred!");
114        // println!("{:?}", val);
115        // set_creation_date(Path::new("./test.txt"), &FileTime::new(5, 12, 3030));
116        // let out = set_attribute(Path::new("./test.txt"), Attributes::READ_ONLY | Attributes::HIDDEN);
117        // println!("{:?}", out);
118        // println!("Has attrib: {:?}", get_attributes(Path::new("./test.txt")));
119        //
120        // let mut r = MessageBox::new("This is a test!", "Wow.png")
121        //     .set_icon_type(IconType::ICON_WARNING)
122        //     .show();
123        //
124        // if r.unwrap() == crate::dialogues::messagebox::BoxReturn::CONTINUE {
125        //     println!("The continue button as pressed!");
126        // }
127        //
128        // let result = FileBox::new().filter("Text", "*.txt")
129        //     .directory(Path::new("D:\\"))
130        //     .save("my_stuff.txt");
131        //
132        // println!("{}", result.expect("There should be a file!").to_str().unwrap());
133        // println!("This is a tst");
134
135        // testnotif();
136        let notif = SimpleNotification::new("Rust Notification".to_string())
137            .set_app_id("{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe".to_string())
138            .add_text("This notification was sent via rust!".to_string())
139            .add_text("This uses the Windows Notification Center.".to_string())
140            .set_hero_image("http://picsum.photos/48?image=883".to_string())
141            .display();
142    }
143}
144
145/*
146
147    Unix tests.
148
149 */
150#[cfg(test)]
151#[cfg(unix)]
152mod tests {
153    use std::fs::File;
154    use std::path::Path;
155
156    use crate::metadata::time::{FileTime, set_creation_date, set_accessed_date, set_changed_date, filetime_to_systime};
157    use crate::metadata::attribute::{set_attribute, Attributes, get_attributes};
158    use crate::processes::processes::{find_process_id, is_process_running};
159    use std::io::Write;
160    use crate::dialogues::filebox::FileBox;
161    use crate::dialogues::messagebox::{MessageBox, IconType, WindowType};
162
163    #[test]
164    fn it_works() {
165        let val = find_process_id(get_test_process()).expect("An error occurred!");
166        println!("{:?}", val);
167        // Test a valid PID.
168        let pid : u32 = 1818;
169        println!("{:?}", is_process_running(&pid));
170
171        let time = FileTime {
172            day: 13,
173            month: 3,
174            year: 2022,
175            hour: 2,
176            minute: 46,
177            second: 46,
178            milliseconds: 0
179        };
180        let systime = filetime_to_systime(&time);
181        assert_eq!(systime,"202203130246.46");
182        set_creation_date(Path::new("./test.txt"), &time);
183        set_changed_date( Path::new("./test.txt"), &time);
184        set_accessed_date( Path::new("./test.txt"), &time);
185    }
186    #[test]
187    fn dialog_open_box() {
188        let option = FileBox::new().filter("Text", "*.txt")
189            .directory(Path::new("/home/")).open();
190        println!("{}", option.unwrap().to_str().unwrap());
191    }
192        #[test]
193        fn dialog_save_box() {
194            let option = FileBox::new().filter("Text", "*.txt")
195                .directory(Path::new("/home/")).save("test.txt");
196            println!("{}", option.unwrap().to_str().unwrap());
197        }
198    #[test]
199    fn message_box() {
200        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
201            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::OK_CANCEL)
202            .show();
203        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
204            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::OK)
205            .show();
206        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
207            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::RETRY_CANCEL)
208            .show();
209        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
210            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::HELP)
211            .show();
212        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
213            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::YES_NO_CANCEL)
214            .show();
215        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
216            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::YES_NO)
217            .show();
218        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
219            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::CANCEL_TRY_CONTINUE)
220            .show();
221        let mut r = MessageBox::new("This is a test!", "Wow I figured out GTK!")
222            .set_icon_type(IconType::ICON_WARNING).set_window_type(WindowType::ABORT_RETRY_IGNORE)
223            .show();
224    }
225    fn get_test_process() -> &'static str {
226        if  cfg!(target_os = "macos") {
227            "launchd"
228        } else if  cfg!(target_os = "linux") {
229            "NetworkManager"
230        } else { "" }
231    }
232
233
234
235    // #[test]
236    // fn attribute_tests(){
237    //     let mut path = Path::new("./se.test");
238    //
239    //     let mut file = File::create(&path).unwrap();
240    //     file.write_all(b"Howdy from System-extensions").unwrap();
241    //     file.sync_all().unwrap();
242    //     set_attribute(path, Attributes::HIDDEN);
243    //     path = Path::new(".se.test");
244    //     assert!(set_attribute(&path, Attributes::READ_ONLY),"Unable to change readonly status");
245    //     let attributes = get_attributes(&path).unwrap();
246    //     assert!(attributes.contains(&Attributes::HIDDEN),"Hidden Attribute missing");
247    //     assert!(attributes.contains(&Attributes::READ_ONLY),"Read ONLY attribute missing");
248    //
249    // }
250}