diff --git a/README.md b/README.md
index d300c13..1739d39 100644
--- a/README.md
+++ b/README.md
@@ -132,6 +132,9 @@ all_runners_in_same_repo: true
 # GitHub Enterprise name
 # github_enterprise: "yourenterprise"
 
+# Runner user Windows password - the logon password for the service user when running on windows.
+# runner_user_win_password: "{{ lookup('env', 'PASS') }}"
+
 # Configuring a custom .env file
 # custom_env: |
 # http_proxy=YOUR_URL_HERE
diff --git a/defaults/main.yml b/defaults/main.yml
index 2c30cbc..78d532e 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -3,7 +3,7 @@
 runner_user: "{{ lookup('env', 'USER') }}"
 
 # Directory where the local runner will be installed
-runner_dir: /opt/actions-runner
+runner_dir: "{{ 'C:\\actions-runner' if ansible_facts.system == 'Win32NT' else '/opt/actions-runner' }}"
 
 # Version of the GitHub Actions Runner
 runner_version: "latest"
@@ -42,7 +42,7 @@ runner_group: ""
 runner_download_repository: "actions/runner"
 
 # Extra arguments to pass to `config.sh`.
-# Several arguments muste be set as one string (i.e. "--ephemeral --my_special_fork")
+# Several arguments must be set as one string (i.e. "--ephemeral --my_special_fork")
 runner_extra_config_args: ""
 
 # Name to assign to this runner in GitHub (System hostname as default)
@@ -63,6 +63,9 @@ all_runners_in_same_repo: true
 # GitHub Enterprise name
 # github_enterprise: "yourenterprise"
 
+# Runner user Windows password - the logon password for the service user when running on windows.
+# runner_user_win_password: "{{ lookup('env', 'PASS') }}"
+
 # Configuring a custom .env file
 # custom_env: |
 # http_proxy=YOUR_URL_HERE
diff --git a/tasks/assert.yml b/tasks/assert.yml
index 2657ca5..6abf982 100644
--- a/tasks/assert.yml
+++ b/tasks/assert.yml
@@ -31,3 +31,11 @@
     fail_msg: "github_repo was not found or is using an invalid format."
   run_once: true
   when: not runner_org and github_enterprise is not defined
+
+- name: Check runner_user_win_password (RUN ONCE)
+  ansible.builtin.assert:
+    that:
+      - runner_user_win_password is defined
+    fail_msg: "runner_user_win_password was not defined, but it is required on a windows system"
+  run_once: true
+  when: github_actions_system == "win"
diff --git a/tasks/collect_info.yml b/tasks/collect_info.yml
index f017e27..a08bf5d 100644
--- a/tasks/collect_info.yml
+++ b/tasks/collect_info.yml
@@ -27,6 +27,8 @@
         status_code: 201
         force_basic_auth: true
       register: registration
+      delegate_to: localhost
+      become: false
       run_once: true
 
     - name: "Check currently registered runners for repo {{ '(RUN ONCE)' if all_runners_in_same_repo else '' }}"
@@ -42,21 +44,21 @@
         status_code: 200
         force_basic_auth: true
       register: registered_runners
+      delegate_to: localhost
+      become: false
       run_once: "{{ all_runners_in_same_repo }}"
 
     - name: Get Runner User IDs
       ansible.builtin.command: id -u "{{ runner_user }}"
       changed_when: false
       register: runner_user_id
+      when: github_actions_system != "win"
 
     - name: Get Runner Group IDs
       ansible.builtin.command: id -g "{{ runner_user }}"
       changed_when: false
       register: runner_user_group_id
-
-    - name: Set runner_system variable
-      ansible.builtin.set_fact:
-        runner_system: "{{ 'osx' if ansible_facts.system == 'Darwin' else 'linux' }}"
+      when: github_actions_system != "win"
 
     - name: Find the latest runner version (RUN ONCE)
       ansible.builtin.uri:
@@ -77,4 +79,4 @@
     - name: Get systemd service facts
       ansible.builtin.service_facts:
       register: service_facts
-      when: ansible_facts.system  == "Linux"
+      when: github_actions_system == "linux"
diff --git a/tasks/install_runner.yml b/tasks/install_runner_unix.yml
similarity index 98%
rename from tasks/install_runner.yml
rename to tasks/install_runner_unix.yml
index ded230d..b398de4 100644
--- a/tasks/install_runner.yml
+++ b/tasks/install_runner_unix.yml
@@ -22,7 +22,7 @@
 - name: Unarchive runner package
   ansible.builtin.unarchive:
     src: "https://github.com/{{ runner_download_repository }}/releases/download/v{{ runner_version }}/\
-          actions-runner-{{ runner_system }}-{{ github_actions_architecture }}-{{ runner_version }}.tar.gz"
+          actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.tar.gz"
     dest: "{{ runner_dir }}/"
     owner: "{{ runner_user_id.stdout }}"
     group: "{{ runner_user_group_id.stdout }}"
diff --git a/tasks/install_runner_win.yml b/tasks/install_runner_win.yml
new file mode 100644
index 0000000..68cdc6b
--- /dev/null
+++ b/tasks/install_runner_win.yml
@@ -0,0 +1,142 @@
+---
+- name: Create directory
+  ansible.windows.win_file:
+    path: "{{ runner_dir }}"
+    state: directory
+
+- name: Set owner of directory
+  ansible.windows.win_owner:
+    path: "{{ runner_dir }}"
+    user: "{{ runner_user }}"
+
+- name: Set runner_version variable (If latest)
+  ansible.builtin.set_fact:
+    runner_version: "{{ api_response.json.tag_name | regex_replace('^v', '') }}"
+  when: runner_version == "latest"
+
+- name: Check if desired version already installed
+  ansible.windows.win_command: "grep -i {{ runner_version }} {{ runner_dir }}\\bin\\Runner.Listener.deps.json"
+  register: runner_installed
+  check_mode: false
+  changed_when: false
+  ignore_errors: true
+
+- name: Download runner package
+  ansible.windows.win_get_url:
+    url: "https://github.com/{{ runner_download_repository }}/releases/download/v{{ runner_version }}/\
+          actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.zip"
+    dest: "%TEMP%\\actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.zip"
+  when: runner_version not in runner_installed.stdout or reinstall_runner
+
+- name: Unarchive runner package
+  community.windows.win_unzip:
+    src: "%TEMP%\\actions-runner-{{ github_actions_system }}-{{ github_actions_architecture }}-{{ runner_version }}.zip"
+    dest: "{{ runner_dir }}\\"
+    delete_archive: yes
+  when: runner_version not in runner_installed.stdout or reinstall_runner
+
+- name: Configure custom env file if required
+  randrej.windows.win_blockinfile:
+    path: "{{ runner_dir }}\\.env"
+    block: "{{ custom_env }}"
+    create: true
+    marker: "# {mark} ANSIBLE MANAGED BLOCK"
+    marker_begin: BEGIN
+    marker_end: END
+  when: custom_env is defined
+
+- name: Check if runner service name file exist
+  ansible.windows.win_stat:
+    path: "{{ runner_dir }}/.service"
+  register: runner_service_file_path
+
+- name: Set complete GitHub url for repo runner
+  ansible.builtin.set_fact:
+    github_full_url: "{{ github_url }}/{{ github_owner | default(github_account) }}/{{ github_repo }}"
+  when: not runner_org and github_enterprise is not defined
+
+- name: Set complete GitHub url for org runner
+  ansible.builtin.set_fact:
+    github_full_url: "{{ github_url }}/{{ github_owner | default(github_account) }}"
+  when: runner_org | bool and github_enterprise is not defined
+
+- name: Set complete GitHub url for enterprise runner
+  ansible.builtin.set_fact:
+    github_full_url: "{{ github_url }}/enterprises/{{ github_enterprise }}"
+  when: github_enterprise is defined
+
+- name: Register runner  # noqa no-changed-when
+  environment:
+    RUNNER_ALLOW_RUNASROOT: "1"
+  ansible.windows.win_command:
+    "{{ runner_dir }}\\config.cmd \
+    --url {{ github_full_url }} \
+    --token {{ registration.json.token }} \
+    --name {{ runner_name }} \
+    --labels {{ runner_labels | join(',') }} \
+    --runnergroup {{ runner_group }} \
+    --runasservice \
+    --windowslogonaccount {{ runner_user }} \
+    --windowslogonpassword {{ runner_user_win_password }} \
+    --unattended \
+    {{ runner_extra_config_args }}"
+  args:
+    chdir: "{{ runner_dir }}"
+  changed_when: true
+  become_method: runas
+  become_user: "{{ runner_user }}"
+  become: true
+  no_log: "{{ hide_sensitive_logs | bool }}"
+  when: runner_name not in registered_runners.json.runners|map(attribute='name')|list
+
+- name: Replace registered runner  # noqa no-changed-when
+  environment:
+    RUNNER_ALLOW_RUNASROOT: "1"
+  ansible.windows.win_command:
+    "{{ runner_dir }}\\config.cmd \
+    --url {{ github_full_url }} \
+    --token {{ registration.json.token }} \
+    --name {{ runner_name }} \
+    --labels {{ runner_labels | join(',') }} \
+    --runasservice \
+    --windowslogonaccount {{ runner_user }} \
+    --windowslogonpassword {{ runner_user_win_password }} \
+    --unattended \
+    {{ runner_extra_config_args }} \
+    --replace"
+  args:
+    chdir: "{{ runner_dir }}"
+  changed_when: true
+  become_method: runas
+  become_user: "{{ runner_user }}"
+  become: true
+  no_log: "{{ hide_sensitive_logs | bool }}"
+  when: >
+    runner_name in registered_runners.json.runners|map(attribute='name')|list and
+    reinstall_runner
+
+- name: Read service name from file
+  ansible.windows.win_command: "cat {{ runner_dir }}\\.service"
+  register: runner_service
+  changed_when: false
+
+- name: START and enable Github Actions Runner service
+  ansible.windows.win_service:
+    name: "{{ runner_service.stdout }}"
+    start_mode: auto
+    state: started
+  when: runner_state|lower == "started"
+
+- name: STOP and disable Github Actions Runner service
+  ansible.windows.win_service:
+    name: "{{ runner_service.stdout }}"
+    start_mode: manual
+    state: stopped
+  when: runner_state|lower == "stopped"
+
+- name: Version changed - RESTART Github Actions Runner service
+  ansible.windows.win_service:
+    name: "{{ runner_service.stdout }}"
+    start_mode: auto
+    state: restarted
+  when: runner_version not in runner_installed.stdout and not runner_state|lower == "stopped"
diff --git a/tasks/main.yml b/tasks/main.yml
index 9884999..b546592 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -5,7 +5,7 @@
     - install
     - uninstall
 
-- name: Include Information collection taks
+- name: Include Information collection tasks
   ansible.builtin.include_tasks: collect_info.yml
   tags:
     - install
@@ -13,18 +13,40 @@
 
 - name: Include tasks to install dependencies
   ansible.builtin.include_tasks: install_deps.yml
-  when: runner_state|lower == "started" or runner_state|lower == "stopped"
+  when:
+    - runner_state|lower == "started" or runner_state|lower == "stopped"
+    - github_actions_system == "linux"
   tags:
     - install
 
-- name: Include tasks to uninstall runner
-  ansible.builtin.include_tasks: uninstall_runner.yml
-  when: reinstall_runner or runner_state|lower == "absent"
+- name: Include tasks to uninstall runner (UNIX-like)
+  ansible.builtin.include_tasks: uninstall_runner_unix.yml
+  when:
+   - reinstall_runner or runner_state|lower == "absent"
+   - github_actions_system == "linux" or github_actions_system == "osx"
   tags:
     - uninstall
 
-- name: Include tasks to install runner
-  ansible.builtin.include_tasks: install_runner.yml
-  when: runner_state|lower == "started" or runner_state|lower == "stopped"
+- name: Include tasks to uninstall runner (Windows)
+  ansible.builtin.include_tasks: uninstall_runner_win.yml
+  when:
+   - reinstall_runner or runner_state|lower == "absent"
+   - github_actions_system == "win"
+  tags:
+    - uninstall
+
+- name: Include tasks to install runner (UNIX-like)
+  ansible.builtin.include_tasks: install_runner_unix.yml
+  when:
+   - runner_state|lower == "started" or runner_state|lower == "stopped"
+   - github_actions_system == "linux" or github_actions_system == "osx"
+  tags:
+    - install
+
+- name: Include tasks to install runner (Windows)
+  ansible.builtin.include_tasks: install_runner_win.yml
+  when:
+   - runner_state|lower == "started" or runner_state|lower == "stopped"
+   - github_actions_system == "win"
   tags:
     - install
diff --git a/tasks/uninstall_runner.yml b/tasks/uninstall_runner_unix.yml
similarity index 100%
rename from tasks/uninstall_runner.yml
rename to tasks/uninstall_runner_unix.yml
diff --git a/tasks/uninstall_runner_win.yml b/tasks/uninstall_runner_win.yml
new file mode 100644
index 0000000..54fd14f
--- /dev/null
+++ b/tasks/uninstall_runner_win.yml
@@ -0,0 +1,47 @@
+---
+- name: Check if runner service name file exist
+  ansible.windows.win_stat:
+    path: "{{ runner_dir }}/.service"
+  register: runner_service_file_path
+
+- name: Read service name from file
+  ansible.windows.win_command: "cat {{ runner_dir }}\\.service"
+  register: runner_service
+  changed_when: false
+  when: runner_service_file_path.stat.exists
+
+- name: Uninstall service runner
+  ansible.windows.win_shell: |
+    if(Get-Service {{ runner_service.stdout }} -ErrorAction SilentlyContinue) {
+      Write-Host "Stopping and removing service: {{ runner_service.stdout }}"
+      sc.exe stop "{{ runner_service.stdout }}"
+      sc.exe delete "{{ runner_service.stdout }}"
+    }
+  args:
+    chdir: "{{ runner_dir }}"
+  register: uninstall_service_runner
+  changed_when: "'Stopping and removing service:' in uninstall_service_runner.stdout"
+  when: runner_service_file_path.stat.exists
+
+- name: Check GitHub Actions runner file
+  ansible.windows.win_stat:
+    path: "{{ runner_dir }}/.runner"
+  register: runner_file
+
+- name: Unregister runner from the GitHub
+  environment:
+    RUNNER_ALLOW_RUNASROOT: "1"
+  ansible.windows.win_command: "config.cmd remove --token {{ registration.json.token }} --name {{ runner_name }} --unattended"
+  args:
+    chdir: "{{ runner_dir }}"
+  become: true
+  become_method: runas
+  become_user: "{{ runner_user }}"
+  no_log: "{{ hide_sensitive_logs | bool }}"
+  changed_when: true
+  when: runner_name in registered_runners.json.runners|map(attribute='name')|list and runner_file.stat.exists
+
+- name: Delete runner directory
+  ansible.windows.win_file:
+    path: "{{ runner_dir }}"
+    state: absent
diff --git a/vars/main.yml b/vars/main.yml
index 4236c1a..4c31c34 100644
--- a/vars/main.yml
+++ b/vars/main.yml
@@ -3,7 +3,13 @@
 github_actions_architecture_map:
   amd64: x64
   x86_64: x64
+  64-bit: x64
   armv7l: arm
   aarch64: arm64
   arm64: arm64
 github_actions_architecture: "{{ github_actions_architecture_map[ansible_facts.architecture] }}"
+github_actions_system_map:
+  Darwin: osx
+  Linux: linux
+  Win32NT: win
+github_actions_system: "{{ github_actions_system_map[ansible_facts.system] }}"